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

Der*_*rek 19 javascript request-cancelling node.js express angularjs

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

有没有办法要求Node.js/Express杀死/停止请求取消的这些待处理请求?

它给出的是,由于AngularJS 1.5 HTTP请求是容易变得特别有用的撤销通过调用$cancelRequest()$http/ $resource对象.

当暴露提供自动完成或搜索字段的结果的API方法时,可能会发生此类取消:在要自动填充的字段中键入或者键入aheaded时,可以取消先前的请求.

全局server.timeout不能解决问题:1)它是所有暴露的API方法的先验全局设置2)取消请求中的持续处理不会被终止.

Der*_*rek 17

注入的req对象随监听器一起提供.on().

监听close事件允许在客户端关闭连接时处理(请求由Angular取消,或者例如,用户关闭查询选项卡).

以下是如何使用close事件来停止请求处理的2个简单示例.

示例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 */);
}
Run Code Online (Sandbox Code Playgroud)

示例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();
}
Run Code Online (Sandbox Code Playgroud)

  • 你可能想听 `"aborted"` 而不是 `"close"`。https://nodejs.org/api/http.html#http_event_aborted (5认同)

Han*_*ung 5

使用Express,您可以尝试:

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

  • 连接/套接字和请求之间有很大的区别。监听连接关闭可能是一个(大)错误(尽管在测试中一切都会正常工作) - 大多数浏览器保持连接打开,尽管请求本身已完成(请参阅“Connection: keep-alive”标头或 HTTP 持久连接术语) ,因此其他请求可以使用相同的底层连接。 (3认同)