确认响应发送太晚; 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 微信公共号开发 - 响应微信发送的Token验证(山东数漫江湖)