使用Express / Node.js和Angular处理已取消的请求

当挂起的HTTP请求被客户端/浏览器取消时,似乎Node with Express继续处理请求。 对于密集的请求,CPU仍然忙于不必要的请求。

有没有办法要求Node.js / Express杀死/停止这些请求被取消的挂起请求?

由于AngularJS 1.5 HTTP请求可以通过在$http / $resource对象上调用$cancelRequest()来轻松取消 ,因此变得特别有用。

当暴露提供自动完成或search字段结果的API方法时,可能会发生这样的取消:当在字段中键入要自动完成或键入的时候,以前的请求可以被取消。

一个全局的server.timeout并不能解决这个问题:1)对于所有暴露的API方法来说,这是一个先验的全局设置。2)在取消的请求中正在进行的处理不会被终止。

注入的req对象与侦听器.on()一起提供。

监听close事件允许处理客户端closures连接(请求被Angular取消,或者,例如,用户closures了查询标签)。

这里有两个简单的例子来说明如何使用close事件来停止请求处理。

示例1:可取消的同步块

 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的可取消asynchronous块(类似于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(); } 

有了快递,您可以尝试:

 req.connection.on('close',function(){ // code to handle connection abort console.log('user cancelled'); }); 

您可以在服务器上设置请求的超时时间 :

 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;