我无法理解为什么我的快递路线遇到'在发送后无法设置标题'

时间:2018-03-10 07:27:47

标签: javascript node.js express

我正在尝试制作机器学习项目(整数序列预测器)。 ML代码是一个python脚本。我试图建立一个快速路由来处理python脚本的stdin和stdout并根据它发送响应。

我在应用程序启动时生成python脚本。

let p = spawn('python', ['python/script.py'], { stdio: ['pipe', 'pipe', process.stderr] });

我的路线

router.get('/', managePredictor);

managePredictor

    function managePredictor(req, res, next) {
  try {
    //timestamp
    let ts = new Date().getTime();
    let token = ts + '_' + magic();
    let seq = req.query.seq;
    let re = new RegExp(token + '((?:\\s|\\S)*)' + token);
    p.stdin.write(token + '\n' + seq + '\n');
    p.stdout.resume();
    p.stdout.on('data', (chunk) => {
      str += chunk;
      let s = re.exec(str);
      let o = JSON.parse(s[1].trim());
      p.stdout.pause();
      res.send(o);
    });
  }
  catch (err) {
    res.status(500).send('Internal Server Error');
  }
}

token是一个类似1520661269162_YGo6p3的字符串。

对于路线的第一次请求,但对于任何连续请求,错误就像

>Error: Can't set headers after they are sent.
>    at validateHeader (_http_outgoing.js:494:11)
>    at ServerResponse.setHeader (_http_outgoing.js:501:3)
>    at ServerResponse.header (D:\mlproj\node_modules\express
>lib\response.js:730:10)
>    at ServerResponse.send (D:\mlproj\node_modules\express >\lib\response.js:170:12)
>    at ServerResponse.json (D:\mlproj\node_modules\express >\lib\response.js:256:15)
>    at ServerResponse.send (D:\mlproj\node_modules\express >\lib\response.js:158:21)
at Socket.p.stdout.on (D:\mlproj\routes\predict.js:39:11)
at emitOne (events.js:121:20)
at Socket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)

Python脚本的IO片段

while True:
ts = input()
inp = input()
arr = inp.split(" ")
arr = list(map(lambda x: int(x), arr))
qq = findNextn(arr, 5)
print(ts)
out = json.dumps({'orignal': arr, 'predicted':qq}, indent=4)
print(out)
print(ts) 

2 个答案:

答案 0 :(得分:1)

p.stdout.on('data', (chunk) => {
   ...
   res.send(o);

每次收到大量数据时都会尝试发送响应。

因此,在请求到达后第一次获得大量数据时,您会发送响应。

然后,当您下次获得一大块数据时,您会尝试再次发送响应。你不能这样做,因为它已经被发送了。

您需要重新思考如何处理HTTP请求与Python程序中的数据之间的交互。

每次从Python进程获取一个块时,您应该将数据存储在一个字符串中,然后使用该字符串的当前内容响应HTTP请求(同时将其重置为空字符串)。

答案 1 :(得分:1)

您需要使用node streams

以下代码应该有效。

function managePredictor(req, res, next) {
    try {
    //timestamp
    let ts = new Date().getTime();
    let token = ts + '_' + magic();
    let seq = req.query.seq;
    let re = new RegExp(token + '((?:\\s|\\S)*)' + token);
    p.stdin.write(token + '\n' + seq + '\n');
    p.stdout.on('open', () => {
      res.pipe(p.stdout)
    })
    p.stdout.on('data', (chunk) => {
      str += chunk;
      let s = re.exec(str);
      let o = JSON.parse(s[1].trim());
      p.stdout.write(o);
    });
    p.stdout.on('end', (chunk) => {
     res.end();
    });
  }
  catch (err) {
    res.status(500).send('Internal Server Error');
  }
}