发送'收到帖子'在异步完成之前回到请求者(NodeJS,ExpressJS)

时间:2018-04-10 19:16:21

标签: node.js express asynchronous post

我有一个API POST路由,我从客户端接收数据并将数据上传到另一个服务。此上传是在post请求(异步)内完成的,需要一段时间。客户端想知道在异步(创建项目功能)完成之前收到了他们的post req。如何在不结束POST的情况下发送? (res.send停止,res.write不会发送出去)

我想在命中此POST路由后立即将http请求发回服务器。 。 。

app.post('/v0/projects', function postProjects(req, res, next) {
  console.log('POST notice to me');

  // *** HERE, I want to send client message 

  // This is the async function
  createProject(req.body, function (projectResponse) {
    projectResponse.on('data', function (data) {
      parseString(data.toString('ascii'), function (err, result) {
        res.message = result;
      });
    });

    projectResponse.on('end', function () {
      if (res.message.error) {
        console.log('MY ERROR: ' + JSON.stringify(res.message.error));
        next(new Error(res));
      } else {
        // *** HERE is where they finally receive a message
        res.status(200).send(res.message); 
      }

    });

    projectResponse.on('error', function (err) {
      res.status(500).send(err.message);
    });
  });
});

内部系统要求在POST请求中调用此createProject函数(需要存在并上传某些内容,否则它不存在) - 否则我将在以后调用它。

谢谢!

1 个答案:

答案 0 :(得分:1)

我认为您无法发送post请求收到的第一个回复,并在内部作业即createProject已完成时发送另一个回复,无论是成功还是失败。

但可能,您可以尝试:

createProject(payload, callback); // i am async will let you know when done! & it will push payload.jobId in doneJobs

可能性1,如果不需要实际的工作回复:

app.post('/v0/projects', function (req, res, next) {
    // call any async job(s) here
    createProject(req.body);
    res.send('Hey Client! I have received post request, stay tuned!');
    next();
  });
});

可能性2,如果需要实际的工作响应,请尝试维护队列:

var q = []; // try option 3 if this is not making sense
var jobsDone = []; // this will be updated by `createProject` callback
app.post('/v0/projects', function (req, res, next) {
    // call async job and push it to queue 
    let randomId = randomId(); // generates random but unique id depending on requests received
    q.push({jobId: randomId }); 
    req.body.jobId = randomId;
    createProject(req.body);
    res.send('Hey Client! I have received post request, stay tuned!');
    next();
  });
});

// hit this api after sometime to know whether job is done or not
app.get('/v0/status/:jobId', function (req, res, next) {
        // check if job is done
        // based on checks if done then remove from **q** or retry or whatever is needed
        let result = jobsDone.indexOf(req.params.jobId) > -1 ? 'Done' : 'Still Processing'; 
        res.send(result);
        next();
      });
    });

可能性3,redis可用于代替可能性2中的内存中队列。

P.S。还有其他选择可以达到预期的效果,但上面提到的是可能的结果。