确认响应发送太晚; NodeJS Express 异步响应

Posted

技术标签:

【中文标题】确认响应发送太晚; NodeJS Express 异步响应【英文标题】:Acknowledge Response sent too late; NodeJS Express Asynchrone Response 【发布时间】:2021-03-15 13:25:50 【问题描述】:

我正在使用带有 express 的 NodeJS。

我收到信息发布者的请求。我必须在收到请求后立即发回确认响应。然后我应该处理请求并返回响应。

根据他们的日志,我发回的确认响应太晚了,而且是在推送了真正的响应之后。这是错误的,不是我想要的。我想跟随这张图片中的模型:

所以我有一个带有以下代码的 router.js 文件:

app.post('/import/message.io', Importer.handleMessage);

在导入控制器中,handleMessage 函数处理请求:

function handleMessage(req, res)
    let otaRequestBuffer = [];
    req.on('readable', () => 
        let data;
        while (data = req.read()) 
            otaRequestBuffer.push(data.toString());
        
    );
    req.on('end', () => 
        let otaRequest = otaRequestBuffer.join('');
        try 
                let parser = new DOMParser();
                let xmlDoc = parser.parseFromString(otaRequest, "text/xml");
                let soapHeader = parseSoapHeader(xmlDoc);
                const soapAction = req.headers['soapaction'].toString();

                // Acknowledge the request; The soapHeader is used in here too. That is why it is after the code above
                res.writeHead(200);
                res.write(
                    `<?xml version='1.0' encoding='utf-8'?> ...
                   `
                );
                res.end();
                // Kick off a new job by adding it to the work queue; Response is send in the consumer.js of this job
                let job = jobs.create('worker-job', args);

                job.on('complete', function(result)
                console.log('Job completed');
                // Other job.on code would be here
                )
        catch (error) 
                console.log(error);
        finally 
          console.log('DevInfo: Finally called here');
       
);

其他见解:

因此确认响应的格式正确。 当我在本地测试时,我会立即收到确认 信息发布者的日志在这里

根据日志,他们的实际响应(第 5 行)似乎在确认响应(第 1 行)之前被推送给他们。

我上面粘贴的代码示例可以做到这一点吗?

感谢您的帮助。

【问题讨论】:

【参考方案1】:

看起来完全有可能在客户端收到确认之前发送真正的响应(推送)。由于 response.end() 是异步的(例如,调用将在响应发送之前完成),我们实际上是在竞速

res.end();

let job = jobs.create('worker-job', args);

这是一种只有在投入生产时才会看到的烦人的事情!

也许您可以在调用 end() 回调后尝试排队您的工作。例如

res.end(() =>  
    console.log("End callback, response stream is complete, starting job...");
    // Kick off a new job by adding it to the work queue; Response is send in the consumer.js of this job
    let job = jobs.create('worker-job', args);
    job.on('complete', function(result)
        console.log('Job completed');
        // Other job.on code would be here
    )
);

自从(来自 Node.js 文档)...

如果指定了回调,它将在响应流完成时调用。

https://nodejs.org/api/http.html#http_response_end_data_encoding_callback

(这是Express用response.end包装的方法) http://expressjs.com/en/5x/api.html#res.end

我还建议在您的服务器上记录详细的时间戳,精确到毫秒,这样您就可以准确地看到调用发生的时间。

setTimeout 方法当然值得一试,它可能会得到你想要的结果:

// Set delay as appropriate
const delayMs = 2000;
setTimeout(() =>  
    console.log("Timeout complete, starting job...");
    // Kick off a new job by adding it to the work queue; Response is send in the consumer.js of this job
    let job = jobs.create('worker-job', args);
    job.on('complete', function(result)
        console.log('Job completed');
        // Other job.on code would be here
    )
, delayMs);

【讨论】:

感谢您的回复!这对我帮助很大。我会及时通知你这在生产中的表现! 不幸的是它不起作用。可以选择 setTimeout 吗? 是的,这可能是您的下一个选择,我会将其添加到答案中! 3000 毫秒的超时也不起作用:/。奇怪......我很快就会深入研究它。 也许 res.send() 是 router.js 文件中的替代方法,因为这也是同步的

以上是关于确认响应发送太晚; NodeJS Express 异步响应的主要内容,如果未能解决你的问题,请参考以下文章

如何在 express/node js 中发送错误 http 响应?

NodeJs/Express 编写 xlsx 模板并将其发送回浏览器下载

Nodejs(express)正在运行但请求不起作用

NodeJS 微信公共号开发 - 响应微信发送的Token验证(山东数漫江湖)

Express/NodeJS + Mongoose App 服务器响应慢

Nodejs - Express JSON 解析器无法响应