web-dev-qa-db-ja.com

JQueryを使ってAjaxリクエストを中止する

JQueryを使って、まだ応答を受け取っていないAjax要求をキャンセル/中止するにはどうすればよいですか。

1734
lukewm

ほとんどのjQuery AjaxメソッドはXMLHttpRequest(または同等の)オブジェクトを返すので、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()

UPDATE: jQuery 1.5では、返されたオブジェクトはjqXHRと呼ばれるネイティブのXMLHttpRequestオブジェクトのラッパーです。このオブジェクトは、すべてのネイティブプロパティとメソッドを公開しているように見えるので、上記の例は引き続き機能します。 jqXHRオブジェクト(jQuery APIドキュメント)を参照してください。

UPDATE 2: jQuery 3以降、ajaxメソッドは追加のメソッド(abortなど)を含むpromiseを返すようになりました。そのため、返されるオブジェクトはxhrではなくなりますが、上記のコードは引き続き機能します。こちらの 3.0ブログを見てください

UPDATE 3 xhr.abort()はまだjQuery 3.xで動作します。 update 2が正しいと仮定しないでください。 jQuery Githubリポジトリの詳細

1672
meouw

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

リクエストオブジェクトで abort() メソッドを使用することもできますが、クライアントはイベントのリスンを停止しますが、 5月 おそらく、サーバーによる処理が停止されることはありません。

110
tvanfosson

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

AJAXリクエストが原因でサーバーが非常に負荷の高い操作を開始している場合は、サーバーを開いてキャンセルリクエストを待機し、別のAJAXリクエスト通知を送信することができます。それがしていることは何でも停止するためのサーバー。

そうでなければ、AJAX応答を単に無視してください。

71
Yuval Adam

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

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

65
Tei

AJAX要求は開始された順序で完了しない場合があります。中止する代わりに、 - ignore all AJAXレスポンスを最新のものを除いて選択できます。

  • カウンターを作る
  • AJAX requestを開始したときにカウンタをインクリメントします
  • Counterの現在の値を使ってリクエストに「スタンプを付ける」
  • 成功コールバックで、スタンプとカウンターを比較して、それが最新の要求かどうかを確認します。

コードの概要

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のデモ

53
Salman A

この問題を回避し、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%確信できません。これがデッドロック状態を引き起こす可能性があります。私たちのテストでは、そのような状況は再現できませんでした。

39
oyophant

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

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

34
Tharindu Kumara

meouwの解決策 は正しいが、もっと細かく制御したい場合は、 Ajax Managerプラグイン jQueryを試してみることができる。

20
Prestaul

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
cuixiping

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

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

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

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

私が解決しようとしていた問題(他の人も遭遇する可能性がある)は、ユーザーが入力フィールドに情報を入力したときに、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);

});

これは基本的に150ミリ秒ごとに1つのリクエストを送信します(自分のニーズに合わせてカスタマイズできる変数)。ここで何が起きているのか正確に理解できない場合は、ifブロックの直前にxhrCountxhrQueueをコンソールに記録してください。

11
brianrhea

信頼できる方法はありませんし、要求が外出したら、私も試しません。合理的に反応する only の方法は 無視する - 応答です。

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

9
comeGetSome

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

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

これを使うことで、継続的な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>
7
Soubhagya Kumar

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

私はポーリングの問題を抱えていた、そして私が原因で私はajaxリクエストを殺したにもかかわらずmysql値が次の50秒間セットされているのでユーザーが更新を見逃したので$ _SESSIONを使用してvarを設定すると、ポーリングが終了して新しいものが開始されるまで自分自身で更新されません。そのため、データベースで0 =オフページとして値を設定しました。ポーリングその行を問い合わせ、falseを返します。 0でポーリングすると明らかに現在の値を取得するので...

これが助けになれば幸いです

5
Marcus

demo を共有しました。これは、データが事前定義された待機時間内にサーバーから返されなかった場合にAJAX requestをキャンセルする方法を示すものです。

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);   
});
3
ganesh

xhr.abort();がページのリロードを引き起こす場合、

それを防ぐために、中止する前にonreadystatechangeをセットすることができます

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