jQueryを使用してAjaxリクエストを中止する


1827

jQueryを使用して、まだ応答を受け取っていないAjaxリクエストキャンセル/中止するにはどうすればよいですか?


2
質問を誤解したかもしれませんが、単に使用できませんでした$.ajaxStopか?
ルークマダンガ2013

17
@LukeMadhanga; ajaxStopすべてのAJAXリクエストが完了したときにのみ検出し、リクエストを停止しないと思います。私の経験では、次のように使用します$(document).ajaxStop(function(){alert("All done")})。使用するの.abort()が最良のオプションです。
TheCarver 2013

回答:


1744

ほとんどのjQuery AjaxメソッドはXMLHttpRequest(または同等の)オブジェクトを返すため、を使用できますabort()

ドキュメントを参照してください:

  • abortメソッドMSDN)。現在のHTTPリクエストをキャンセルします。
  • abort()MDN)。リクエストがすでに送信されている場合、このメソッドはリクエストを中止します。
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 3xhr.abort()jQuery 3.xでも動作します。アップデート2が正しいと思い込まないでください。jQuery Githubリポジトリの詳細


12
これは、ブラウザの「停止」ボタンをクリックするようなものです。リクエストをキャンセルします。その後、同じXHRオブジェクトを別のリクエストに再利用できます。
meouw

65
@brad残念ながら、abortサーバーとの確立された接続を閉じないため、success引き続き呼び出されます。これは、長いポーリングを行うCometの実装にとって非常に問題です。
pepkin88 2011年

6
@ErvWalter前のリクエストをキャンセルする別のリクエストをディスパッチできます。
Asad Saeeduddin

8
私のテストでは、リクエストはブラウザで中止されますが、.fail()メソッドはjqXHR、status = 0およびjqXHR、statusMessage = "abort"で呼び出されます
BJ Safdie

9
.abort()jQuery 3.2.1ではまだ動作します。jQueryコアチームメンバーによる関連するgithubの問題でのこのコメントは、この回答が正しくないことを意味するようで、.abort() 削除されませんでした。
2017年

117

リクエストを取り消すことはできませんが、タイムアウト値を設定すると、応答は無視されます。jquery AJAXオプションについては、このページを参照してください。タイムアウト期間を超えると、エラーコールバックが呼び出されると思います。すべてのAJAX要求には、すでにデフォルトのタイムアウトがあります。

リクエストオブジェクトでabort()メソッドを使用することもできますが、これによりクライアントはイベントのリスニングを停止しますが、サーバーによるイベントの処理を停止しない可能性があります。


74

これは非同期要求です。つまり、送信されるとそこにあります。

AJAXリクエストが原因でサーバーが非常に負荷の高い操作を開始している場合、最善の方法は、サーバーを開いてキャンセルリクエストをリッスンし、別のAJAXリクエストを送信してサーバーに通知し、実行中の処理をすべて停止することです。

それ以外の場合は、AJAX応答を無視してください。


48
このコンテキストでは、非同期とは、要求がスクリプトのフローを中断しないことを意味します。ブラウザには、リクエストが完了する前にリクエストを途中で中止する機能があります。
ElephantHunter

4
キャンセル要求をサーバーに送信するにはどうすればよいですか?サーバーが処理を停止する要求をどのように認識するかわかりませんか?例を挙げていただけますか?ありがとうございました。
Lucky Soni

3
@ LuckySoni、Elephanthunterはクライアント側についてのみ議論しています。サーバーは.abortリクエストの影響を受けません
Kloar 2014

4
@Kloar、リクエストがサーバーによってまだ受信されていない場合(f.ex.大きなマルチパートリクエストなど)、クライアントがソケットを閉じる可能性があり、サーバーが影響を受けます。

4
PHPは中止されたリクエストを自動的にチェックし、自動的に終了します。php.net/manual/en/function.ignore-user-abort.phpを
hanshenrik

68

作成した呼び出しを配列に保存し、それぞれに対してxhr.abort()を呼び出します。

大きな警告:リクエストを中止できますが、それはクライアント側のみです。サーバー側はまだ要求を処理している可能性があります。PHPまたはASPなどのセッションデータを使用している場合、セッションデータはajaxが完了するまでロックされます。したがって、ユーザーが引き続きWebサイトを閲覧できるようにするには、session_write_close()を呼び出す必要があります。これにより、セッションが保存されてロックが解除され、続行を待機している他のページが続行されます。これがなければ、ロックが解除されるのをいくつかのページが待っている可能性があります。


あなたはいつも前のものをキャンセルするので、あなたはいつもそれをすることはできませんか?(および配列を使用する必要はありません)
非極性

60

AJAX要求は、開始された順序で完了しない場合があります。中止する代わりに、最新のものを除くすべての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

jsFiddleのデモ


XHRリクエストをキャンセルする際の注意事項(このページの他のコメントを参照)のため、これはおそらく最良かつ最も簡単なオプションです。
Quinn Comendant

41

この問題を回避し、3つの異なるアプローチをテストする必要がありました。

  1. @meouwの提案に従ってリクエストをキャンセルします
  2. すべてのリクエストを実行しますが、最後の送信の結果のみを処理します
  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%確実ではありません。これにより、デッドロック状態が発生する可能性があります。私たちのテストでは、そのような状況を再現することはできませんでした。


36

このようなことをすることが常にベストプラクティスです。

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かどうかをチェックする方がはるかに優れています。


2
リクエストがすでに実行されているかどうかも確認しますが、軽量なのでブール値を使用します。
Zesty 2015

15

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);

13

私はライブ検索ソリューションを実行していて、最新の/最新のリクエストよりも時間がかかる可能性がある保留中のリクエストをキャンセルする必要がありました。

私の場合、私はこのようなものを使用しました:

//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 

12

スレッド上の多くの人が指摘したように、要求がクライアント側で中止されたからといって、サーバーは引き続き要求を処理します。これは、フロントエンドでのリッスンを中止した作業を行っているため、サーバーに不要な負荷をかけます。

私が解決しようとしていた問題(他のユーザーも実行する可能性がある)は、ユーザーが入力フィールドに情報を入力したときに、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つのリクエストが送信されます(独自のニーズに合わせてカスタマイズできる変数)。ここで何が起こっているのか正確に理解できない場合は、ログインxhrCountxhrQueueて、ifブロックの直前のコンソールにアクセスしてください。


11

ajax.abort()を使用するだけです。たとえば、このような別のajaxリクエストを送信する前に、保留中のajaxリクエストを中止できます。

//check for existing ajax request
if(ajax){ 
 ajax.abort();
 }
//then you make another ajax request
$.ajax(
 //your code here
  );

11

これを使用して、継続的な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>

10

信頼できる方法はありません。リクエストが送信されたら、私も試しません。合理的に反応する唯一の方法は、応答を無視することです。

ほとんどの場合、それは次のような状況で発生する可能性があります。ユーザーがボタンを頻繁にクリックして多数の連続したXHRをトリガーするユーザーに寄り掛かる-または、保留中のXHR応答以外の最近の応答を破棄する。


7

次のコードは、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!" >

5
これにより問題がどのように解決されるかについて説明してください。これは、OPや他の将来の検索者に役立ちます。
SnareChops 2016年

5

私はポーリングの問題があり、ページが閉じられた後もポーリングが続行されたため、私の理由では、ページが閉じられてから次の50秒間にmysql値が設定されているため、ユーザーは更新を見逃すことになります。 $ _SESSIONを使用してvarを設定すると、終了して新しいものが開始されるまでポーリングで更新されないため、データベース内の値を0 = offpageに設定しました。ポーリングその行をクエリしてfalseを返します。ポーリングでクエリを実行すると現在の値が明らかに得られるため、0の場合...

これが役に立てば幸い


5

xhr.abort(); ページの再読み込みが発生する場合 、

次に、onreadystatechange中止する前に設定して、次のことを防止できます。

// ↓ prevent page reload by abort()
xhr.onreadystatechange = null;
// ↓ may cause page reload
xhr.abort();

4

デモを共有しました事前定義された待機時間内にサーバーからデータが返されない場合に、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);   
});

1
$.ajaxtimeoutオプションを提供するので、独自に記述する必要はありません。単に使用します..., data: {...}, timeout: waitTime,...
Bram Vanroy 16
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.