【问题标题】:Send 'Received post' back to requester before async finishes (NodeJS, ExpressJS)在异步完成之前将“收到的帖子”发送回请求者(NodeJS,ExpressJS)
【发布时间】:2018-09-20 12:41:07
【问题描述】:

我有一个 API 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 函数(需要存在并上传一些内容,否则不存在)——否则我稍后会调用它。

谢谢!

【问题讨论】:

    标签: node.js express asynchronous post


    【解决方案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 中的内存队列。

    附:还有其他可用的选项来实现预期的结果,但上面提到的都是可能的。

    【讨论】:

    • res.send会退出post请求并停止createProject异步函数吗?
    • 不,它不会停止任何异步操作,异步作业将继续自行处理,您可以再次阅读我的答案以获得完整的想法和理解
    猜你喜欢
    • 1970-01-01
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 2019-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-26
    相关资源
    最近更新 更多