使用 Express/Node.js 和 Angular 处理取消的请求
Posted
技术标签:
【中文标题】使用 Express/Node.js 和 Angular 处理取消的请求【英文标题】:Handling cancelled request with Express/Node.js and Angular 【发布时间】:2016-05-13 21:34:29 【问题描述】:当客户端/浏览器取消挂起的 HTTP 请求时,Node with Express 似乎会继续处理该请求。对于密集的请求,CPU 仍然忙于处理不必要的请求。
有没有办法让 Node.js/Express 终止/停止这些请求取消的待处理请求?
鉴于 AngularJS 1.5 HTTP 请求很容易通过在 $http
/$resource
对象上调用 $cancelRequest()
来实现 cancellable,因此它变得特别有用。
当公开为自动完成或搜索字段提供结果的 API 方法时,可能会发生这种取消:在要自动完成或预先输入的字段中键入时,可以取消先前的请求。
全局 server.timeout
不能解决问题:1) 它是所有公开 API 方法的先验全局设置 2) 取消请求中正在进行的处理不会被终止。
【问题讨论】:
【参考方案1】:用express,你可以试试:
req.connection.on('close',function()
// code to handle connection abort
console.log('user cancelled');
);
【讨论】:
connection/socket和request有很大区别。监听连接关闭可能是一个(大)错误(尽管在测试中一切都会正常工作) - 大多数浏览器保持连接打开,尽管请求本身已完成(请参阅“连接:保持活动”标头或 HTTP 持久连接术语) ,因此其他请求可以使用相同的底层连接。【参考方案2】:注入的req
object 与侦听器.on()
一起提供。
侦听close
事件允许在客户端关闭连接时进行处理(请求被 Angular 取消,或者,例如,用户关闭了查询选项卡)。
这里有两个简单的例子,如何使用close
event 来停止请求处理。
示例一:可取消同步块
var clientCancelledRequest = 'clientCancelledRequest';
function cancellableAPIMethodA(req, res, next)
var cancelRequest = false;
req.on('close', function (err)
cancelRequest = true;
);
var superLargeArray = [/* ... */];
try
// Long processing loop
superLargeArray.forEach(function (item)
if (cancelRequest)
throw type: clientCancelledRequest;
/* Work on item */
);
// Job done before client cancelled the request, send result to client
res.send(/* results */);
catch (e)
// Re-throw (or call next(e)) on non-cancellation exception
if (e.type !== clientCancelledRequest)
throw e;
// Job done before client cancelled the request, send result to client
res.send(/* results */);
示例 2:带有 promise 的可取消异步块(类似于 reduce)
function cancellableAPIMethodA(req, res, next)
var cancelRequest = false;
req.on('close', function (err)
cancelRequest = true;
);
var superLargeArray = [/* ... */];
var promise = Q.when();
superLargeArray.forEach(function (item)
promise = promise.then(function()
if (cancelRequest)
throw type: clientCancelledRequest;
/* Work on item */
);
);
promise.then(function()
// Job done before client cancelled the request, send result to client
res.send(/* results */);
)
.catch(function(err)
// Re-throw (or call next(err)) on non-cancellation exception
if (err.type !== clientCancelledRequest)
throw err;
)
.done();
【讨论】:
您可能想收听"aborted"
而不是"close"
。 nodejs.org/api/http.html#http_event_aborted【参考方案3】:
您可以为服务器上的请求设置timeout:
var server = app.listen(app.get('port'), function()
debug('Express server listening on port ' + server.address().port);
);
// Set the timeout for a request to 1sec
server.timeout = 1000;
【讨论】:
我想在客户要求取消时立即取消请求。对自动完成查询很有用。 我在关于这种情况的问题中添加了一些 cmets:全局 server.timeout 不能解决问题:1)它是所有公开 API 方法的先验全局设置 2)正在进行的处理在取消的请求中不会被杀死。 谢谢。我会调查的。以上是关于使用 Express/Node.js 和 Angular 处理取消的请求的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Express / Node.JS 创建可在所有视图中访问的全局变量?
请求新页面时如何将 AngularJS 路由与 Express (Node.js) 一起使用?