保留中のHTTPリクエストがクライアント/ブラウザによってキャンセルされると、Nodeはリクエストの処理を続行します。集中的なリクエストの場合、CPUは不要なリクエストでビジー状態になっています。
キャンセルするように要求されているこれらの保留中の要求を殺す/停止するようにNode.js/Expressに要求する方法はありますか?
AngularJS 1.5 HTTPリクエストは_$http
_/_$resource
_オブジェクトで$cancelRequest()
を呼び出すことで簡単に cancellable になるので、特に役立ちます。
このようなキャンセルは、オートコンプリートまたは検索フィールドの結果を提供するAPIメソッドを公開するときに発生する可能性があります。オートコンプリートまたは先行入力されるフィールドに入力すると、以前のリクエストがキャンセルされる場合があります。
グローバル_server.timeout
_は問題を解決しません。1)すべての公開されたAPIメソッドのグローバル設定であり、2)キャンセルされたリクエストで進行中の処理は強制終了されません。
注入されたreq
objectには、リスナー.on()
が付属しています。
close
イベントをリッスンすると、クライアントが接続を閉じたときに処理できます(Angularによってキャンセルされた要求、またはユーザーがクエリタブを閉じたなど)。
close
eventを使用してリクエスト処理を停止する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();
}
Expressを使用すると、次のことを試すことができます。
req.connection.on('close',function(){
// code to handle connection abort
console.log('user cancelled');
});