web-dev-qa-db-ja.com

Express / Node.jsおよびAngular

保留中のHTTPリクエストがクライアント/ブラウザによってキャンセルされると、Nodeはリクエストの処理を続行します。集中的なリクエストの場合、CPUは不要なリクエストでビジー状態になっています。

キャンセルするように要求されているこれらの保留中の要求を殺す/停止するようにNode.js/Expressに要求する方法はありますか?

AngularJS 1.5 HTTPリクエストは_$http_/_$resource_オブジェクトで$cancelRequest()を呼び出すことで簡単に cancellable になるので、特に役立ちます。

このようなキャンセルは、オートコンプリートまたは検索フィールドの結果を提供するAPIメソッドを公開するときに発生する可能性があります。オートコンプリートまたは先行入力されるフィールドに入力すると、以前のリクエストがキャンセルされる場合があります。

グローバル_server.timeout_は問題を解決しません。1)すべての公開されたAPIメソッドのグローバル設定であり、2)キャンセルされたリクエストで進行中の処理は強制終了されません。

22
Derek

注入されたreqobjectには、リスナー.on()が付属しています。

closeイベントをリッスンすると、クライアントが接続を閉じたときに処理できます(Angularによってキャンセルされた要求、またはユーザーがクエリタブを閉じたなど)。

closeeventを使用してリクエスト処理を停止する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 */);
}

例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();
}
20
Derek

Expressを使用すると、次のことを試すことができます。

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