Joeyboy
Joeyboy

Reputation: 472

Wait for a python script to run before sending a response Node Express

Upon clicking a button on the frontend, I would like to execute a python script which takes between 10 - 30 seconds to run.

I am trying to call the python script in my post route/controller but am getting the following error:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

I would not like to send anything to the client until after the script has run.

Route/Controller:

const express = require("express");
const router = express.Router();

router.post("/solve", async function (req, res) {
  const board = JSON.stringify({
    board: req.body.grid,
  });

  const spawn = require("child_process").spawn;
  const pythonProcess = spawn("python", ["./crossword/crossword.py", board]);
  pythonProcess.stdout.on("data", (data) => {
    // Do something with the data returned from python script
    solved_data = JSON.parse(data.toString());
    res.send(JSON.stringify(solved_data));
  });
});

Upvotes: 0

Views: 632

Answers (1)

Zain Ul Abidin
Zain Ul Abidin

Reputation: 2710

The error is shown because you are sending data in the data event which keeps on firing on every output change by python script which repeatedly sends the response to client (which is not good), to solve the issue you should send response only once and for that you should subscribe to the exit event of the process so that collect all output and then send the output as response when process is closed

const express = require("express");
const router = express.Router();
let data = '';

router.post("/solve", async function (req, res) {
  const board = JSON.stringify({
    board: req.body.grid,
  });

  const spawn = require("child_process").spawn;
  const pythonProcess = spawn("python", ["./crossword/crossword.py", board]);
  pythonProcess.stdout.on("data", (response) => {
    // Keep collecting the data from python script
    data += response;
  });

  pythonProcess.on('exit', function(code, signal) {
    console.log('Python process is now completed send data as response');
    let solved_data = JSON.parse(data);
    res.send(JSON.stringify(solved_data));
    //you can also check code to verify if exit was due to error or normal
  });
});

Upvotes: 1

Related Questions