Nodejs:通过调用异步服务同步响应请求
Nodejs: Responding synchronously to a request by calling an asynchronous service
我正在编写一个基于 Nodejs 的服务 N,它位于实体 A 和 B 之间。
A <----> N <----> B
应用程序 A POST
向 N 发出同步请求,N 必须使用它只能通过调用外部服务 B 获取的数据来响应该请求。
问题是,B 是异步的service/API:任何 N POST
s 到 B 都会首先响应 HTTP 202 ("request accepted"),然后将实际数据作为回调 POST
从 B 到 N 的请求。因此,本质上,在单线程 N 中,我必须以某种方式在 N 和 B 之间的异步消息交换完成以服务当前暂停的 A 请求时,保持来自 A 的当前同步请求“暂停”,而不会阻止从 A 到 N 的其他潜在请求。
这在 Nodejs 中是否可行,比如说,使用 promises 或 async
/await
魔法?
使用请求 ID、本地缓存和超时,您可以这样做:
const requestIdAndResponseDetailsMap = {};
router.post('/request-from-a', function requestFromAHandler(request, response) {
const requestId = request.body.id;
makeCallToB(request.body); // ensure that request id is passed to B and sent in the call from B to N.
cacheServiceAResponseWithTimeout(requestId, response);
});
router.post('/callback-from-b', function callbackFromBHandler(request, response) {
const dataFromB = request.body;
tryRespondToA(dataFromB);
response.json({ success: true });
});
function tryRespondToA(responseFromB) {
const requestId = responseFromB.id;
const cachedData = requestIdAndResponseDetailsMap[requestId];
if(cachedData === undefined) {
return;
}
delete requestIdAndResponseDetailsMap[requestId];
clearTimeout(cachedData.timerReference);
cachedData.response.json(responseFromB);
}
function cacheServiceAResponseWithTimeout(requestId, response) {
const timerReference = setTimeout(function timerCallback() {
const cachedData = requestIdAndResponseDetailsMap[requestId];
delete requestIdAndResponseDetailsMap[requestId];
cachedData.response.json({ message: 'Service B request timed out' });
}, TIMEOUT_IN_MILLISECONDS);
requestIdAndResponseDetailsMap[requestId] = { response, timerReference };
}
我正在编写一个基于 Nodejs 的服务 N,它位于实体 A 和 B 之间。
A <----> N <----> B
应用程序 A POST
向 N 发出同步请求,N 必须使用它只能通过调用外部服务 B 获取的数据来响应该请求。
问题是,B 是异步的service/API:任何 N POST
s 到 B 都会首先响应 HTTP 202 ("request accepted"),然后将实际数据作为回调 POST
从 B 到 N 的请求。因此,本质上,在单线程 N 中,我必须以某种方式在 N 和 B 之间的异步消息交换完成以服务当前暂停的 A 请求时,保持来自 A 的当前同步请求“暂停”,而不会阻止从 A 到 N 的其他潜在请求。
这在 Nodejs 中是否可行,比如说,使用 promises 或 async
/await
魔法?
使用请求 ID、本地缓存和超时,您可以这样做:
const requestIdAndResponseDetailsMap = {};
router.post('/request-from-a', function requestFromAHandler(request, response) {
const requestId = request.body.id;
makeCallToB(request.body); // ensure that request id is passed to B and sent in the call from B to N.
cacheServiceAResponseWithTimeout(requestId, response);
});
router.post('/callback-from-b', function callbackFromBHandler(request, response) {
const dataFromB = request.body;
tryRespondToA(dataFromB);
response.json({ success: true });
});
function tryRespondToA(responseFromB) {
const requestId = responseFromB.id;
const cachedData = requestIdAndResponseDetailsMap[requestId];
if(cachedData === undefined) {
return;
}
delete requestIdAndResponseDetailsMap[requestId];
clearTimeout(cachedData.timerReference);
cachedData.response.json(responseFromB);
}
function cacheServiceAResponseWithTimeout(requestId, response) {
const timerReference = setTimeout(function timerCallback() {
const cachedData = requestIdAndResponseDetailsMap[requestId];
delete requestIdAndResponseDetailsMap[requestId];
cachedData.response.json({ message: 'Service B request timed out' });
}, TIMEOUT_IN_MILLISECONDS);
requestIdAndResponseDetailsMap[requestId] = { response, timerReference };
}