jQueryを使用して、まだ応答を受け取っていないAjaxリクエストをキャンセル/中止するにはどうすればよいですか?
ajaxStop
すべてのAJAXリクエストが完了したときにのみ検出し、リクエストを停止しないと思います。私の経験では、次のように使用します$(document).ajaxStop(function(){alert("All done")})
。使用するの.abort()
が最良のオプションです。
jQueryを使用して、まだ応答を受け取っていないAjaxリクエストをキャンセル/中止するにはどうすればよいですか?
ajaxStop
すべてのAJAXリクエストが完了したときにのみ検出し、リクエストを停止しないと思います。私の経験では、次のように使用します$(document).ajaxStop(function(){alert("All done")})
。使用するの.abort()
が最良のオプションです。
回答:
ほとんどのjQuery AjaxメソッドはXMLHttpRequest(または同等の)オブジェクトを返すため、を使用できますabort()
。
ドキュメントを参照してください:
var xhr = $.ajax({
type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function(msg){
alert( "Data Saved: " + msg );
}
});
//kill the request
xhr.abort()
更新: jQuery 1.5以降、返されるオブジェクトは、jqXHRと呼ばれるネイティブXMLHttpRequestオブジェクトのラッパーです。このオブジェクトはすべてのネイティブプロパティとメソッドを公開しているように見えるため、上記の例は引き続き機能します。jqXHRオブジェクト(jQuery APIドキュメント)を参照してください。
更新2:
jQuery 3の時点で、ajaxメソッドは追加のメソッド(abortなど)を持つpromiseを返すようになりました。そのため、返されるオブジェクトはxhr
もうありませんが、上記のコードは引き続き機能します。こちらの3.0ブログをご覧ください。
UPDATE 3:xhr.abort()
jQuery 3.xでも動作します。アップデート2が正しいと思い込まないでください。jQuery Githubリポジトリの詳細。
abort
サーバーとの確立された接続を閉じないため、success
引き続き呼び出されます。これは、長いポーリングを行うCometの実装にとって非常に問題です。
.abort()
jQuery 3.2.1ではまだ動作します。jQueryコアチームメンバーによる関連するgithubの問題でのこのコメントは、この回答が正しくないことを意味するようで、.abort()
削除されませんでした。
これは非同期要求です。つまり、送信されるとそこにあります。
AJAXリクエストが原因でサーバーが非常に負荷の高い操作を開始している場合、最善の方法は、サーバーを開いてキャンセルリクエストをリッスンし、別のAJAXリクエストを送信してサーバーに通知し、実行中の処理をすべて停止することです。
それ以外の場合は、AJAX応答を無視してください。
作成した呼び出しを配列に保存し、それぞれに対してxhr.abort()を呼び出します。
大きな警告:リクエストを中止できますが、それはクライアント側のみです。サーバー側はまだ要求を処理している可能性があります。PHPまたはASPなどのセッションデータを使用している場合、セッションデータはajaxが完了するまでロックされます。したがって、ユーザーが引き続きWebサイトを閲覧できるようにするには、session_write_close()を呼び出す必要があります。これにより、セッションが保存されてロックが解除され、続行を待機している他のページが続行されます。これがなければ、ロックが解除されるのをいくつかのページが待っている可能性があります。
AJAX要求は、開始された順序で完了しない場合があります。中止する代わりに、最新のものを除くすべてのAJAX応答を無視することを選択できます。
コードの大まかな概要:
var xhrCount = 0;
function sendXHR() {
// sequence number for the current invocation of function
var seqNumber = ++xhrCount;
$.post("/echo/json/", { delay: Math.floor(Math.random() * 5) }, function() {
// this works because of the way closures work
if (seqNumber === xhrCount) {
console.log("Process the response");
} else {
console.log("Ignore the response");
}
});
}
sendXHR();
sendXHR();
sendXHR();
// AJAX requests complete in any order but only the last
// one will trigger "Process the response" message
この問題を回避し、3つの異なるアプローチをテストする必要がありました。
var Ajax1 = {
call: function() {
if (typeof this.xhr !== 'undefined')
this.xhr.abort();
this.xhr = $.ajax({
url: 'your/long/running/request/path',
type: 'GET',
success: function(data) {
//process response
}
});
}
};
var Ajax2 = {
counter: 0,
call: function() {
var self = this,
seq = ++this.counter;
$.ajax({
url: 'your/long/running/request/path',
type: 'GET',
success: function(data) {
if (seq === self.counter) {
//process response
}
}
});
}
};
var Ajax3 = {
active: false,
call: function() {
if (this.active === false) {
this.active = true;
var self = this;
$.ajax({
url: 'your/long/running/request/path',
type: 'GET',
success: function(data) {
//process response
},
complete: function() {
self.active = false;
}
});
}
}
};
$(function() {
$('#button').click(function(e) {
Ajax3.call();
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="button" type="button" value="click" />
私たちのケースでは、サーバーへの負荷が少ないアプローチ#3を使用することにしました。しかし、jQueryが.complete()メソッドの呼び出しを保証するかどうかは、100%確実ではありません。これにより、デッドロック状態が発生する可能性があります。私たちのテストでは、そのような状況を再現することはできませんでした。
このようなことをすることが常にベストプラクティスです。
var $request;
if ($request != null){
$request.abort();
$request = null;
}
$request = $.ajax({
type : "POST", //TODO: Must be changed to POST
url : "yourfile.php",
data : "data"
}).done(function(msg) {
alert(msg);
});
しかし、ifステートメントをチェックして、ajaxリクエストがnullかどうかをチェックする方がはるかに優れています。
xhrを呼び出すだけです。abort() jquery ajaxオブジェクトであるか、ネイティブXMLHTTPRequestオブジェクトであるか。
例:
//jQuery ajax
$(document).ready(function(){
var xhr = $.get('/server');
setTimeout(function(){xhr.abort();}, 2000);
});
//native XMLHTTPRequest
var xhr = new XMLHttpRequest();
xhr.open('GET','/server',true);
xhr.send();
setTimeout(function(){xhr.abort();}, 2000);
私はライブ検索ソリューションを実行していて、最新の/最新のリクエストよりも時間がかかる可能性がある保留中のリクエストをキャンセルする必要がありました。
私の場合、私はこのようなものを使用しました:
//On document ready
var ajax_inprocess = false;
$(document).ajaxStart(function() {
ajax_inprocess = true;
});
$(document).ajaxStop(function() {
ajax_inprocess = false;
});
//Snippet from live search function
if (ajax_inprocess == true)
{
request.abort();
}
//Call for new request
スレッド上の多くの人が指摘したように、要求がクライアント側で中止されたからといって、サーバーは引き続き要求を処理します。これは、フロントエンドでのリッスンを中止した作業を行っているため、サーバーに不要な負荷をかけます。
私が解決しようとしていた問題(他のユーザーも実行する可能性がある)は、ユーザーが入力フィールドに情報を入力したときに、Googleインスタントタイプのフィールのリクエストを開始したかったということです。
不要なリクエストの発生を回避し、フロントエンドの迅速さを維持するために、次のことを行いました。
var xhrQueue = [];
var xhrCount = 0;
$('#search_q').keyup(function(){
xhrQueue.push(xhrCount);
setTimeout(function(){
xhrCount = ++xhrCount;
if (xhrCount === xhrQueue.length) {
// Fire Your XHR //
}
}, 150);
});
これにより、基本的に150msごとに1つのリクエストが送信されます(独自のニーズに合わせてカスタマイズできる変数)。ここで何が起こっているのか正確に理解できない場合は、ログインxhrCount
しxhrQueue
て、ifブロックの直前のコンソールにアクセスしてください。
ajax.abort()を使用するだけです。たとえば、このような別のajaxリクエストを送信する前に、保留中のajaxリクエストを中止できます。
//check for existing ajax request
if(ajax){
ajax.abort();
}
//then you make another ajax request
$.ajax(
//your code here
);
これを使用して、継続的なajax呼び出しを中止できます
<input id="searchbox" name="searchbox" type="text" />
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript">
var request = null;
$('#searchbox').keyup(function () {
var id = $(this).val();
request = $.ajax({
type: "POST", //TODO: Must be changed to POST
url: "index.php",
data: {'id':id},
success: function () {
},
beforeSend: function () {
if (request !== null) {
request.abort();
}
}
});
});
</script>
信頼できる方法はありません。リクエストが送信されたら、私も試しません。合理的に反応する唯一の方法は、応答を無視することです。
ほとんどの場合、それは次のような状況で発生する可能性があります。ユーザーがボタンを頻繁にクリックして多数の連続したXHRをトリガーするユーザーに寄り掛かる-または、保留中のXHR応答以外の最近の応答を破棄する。
次のコードは、Ajaxリクエストの開始と中止を示しています。
function libAjax(){
var req;
function start(){
req = $.ajax({
url: '1.php',
success: function(data){
console.log(data)
}
});
}
function stop(){
req.abort();
}
return {start:start,stop:stop}
}
var obj = libAjax();
$(".go").click(function(){
obj.start();
})
$(".stop").click(function(){
obj.stop();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="button" class="go" value="GO!" >
<input type="button" class="stop" value="STOP!" >
デモを共有しました事前定義された待機時間内にサーバーからデータが返されない場合に、AJAXリクエストをキャンセルする方法を示すを。
HTML:
<div id="info"></div>
JSコード:
var isDataReceived= false, waitTime= 1000;
$(function() {
// Ajax request sent.
var xhr= $.ajax({
url: 'http://api.joind.in/v2.1/talks/10889',
data: {
format: 'json'
},
dataType: 'jsonp',
success: function(data) {
isDataReceived= true;
$('#info').text(data.talks[0].talk_title);
},
type: 'GET'
});
// Cancel ajax request if data is not loaded within 1sec.
setTimeout(function(){
if(!isDataReceived)
xhr.abort();
},waitTime);
});
$.ajaxStop
か?