jQuery AJAXリクエストをキャンセル/中止する方法は?


244

5秒ごとに行われるAJAXリクエストがあります。しかし、問題はAJAXリクエストの前にあります。前のリクエストが完了していない場合、そのリクエストを中止して新しいリクエストを作成する必要があります。

私のコードはこのようなものです、この問題を解決するにはどうすればよいですか?

$(document).ready(
    var fn = function(){
        $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            }
        });
    };

    var interval = setInterval(fn, 500);
);


5
あなたの質問では、リクエストは5秒ごとに発生するはずですが、コードでは500ミリ秒= 0.5秒を使用しています。
geon 2013年

回答:


355

jquery ajaxメソッドはXMLHttpRequestオブジェクトを返します。このオブジェクトを使用して、リクエストをキャンセルできます。

XMLHttpRequestには、要求をキャンセルするabortメソッドがありますが、要求がすでにサーバーに送信されている場合は、要求を中断してもサーバーは要求を処理しますが、クライアントは応答を待機/処理しません。

xhrオブジェクトには、リクエストの状態(UNSENT-0、OPENED-1、HEADERS_RECEIVED-2、LOADING-3、DONE-4)を含むreadyStateも含まれています。これを使用して、前のリクエストが完了したかどうかを確認できます。

$(document).ready(
    var xhr;

    var fn = function(){
        if(xhr && xhr.readyState != 4){
            xhr.abort();
        }
        xhr = $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            }
        });
    };

    var interval = setInterval(fn, 500);
);

60
@romkyns違いはプロパティでありreadystate、上記とreadyState下の、文字がs1.5 jQueryの資産計上された
アルンPジョニー

readyStateが "LOADING-3"で、中止するとどうなるのだろうと思っていました。データはサーバーに送信され、処理されるかどうかが決まります。わかりません...:S
inf3rno 2013年

7
ところで、readyStateチェックは据え置かれ、解決または拒否されると他のチェックは実行されないため、不要だと思います。だからif (xhr) xhr.abort();うまくいきます。
Ciantic 2013年

2
W3はreadystate、そのドキュメントで大文字を使用せずに使用していません。常に大文字で表記されreadyState、jquery(1.5より前または後)はw3仕様に正しく一致します。
Arashsoft 2016

@ArunPJohnyは、あなたがこの質問plsをすることができますstackoverflow.com/questions/49801146/...
クリシュナJonnalagadda

6

サーバーにリクエストを送信するときは、まず進行状況がnullでないかどうか(またはそのデータをフェッチしていないかどうか)を確認してください。データをフェッチしている場合は、前の要求を中止して、新しい要求を開始します。

var progress = null

function fn () {    
    if (progress) {
        progress.abort();
    }
    progress = $.ajax('ajax/progress.ftl', {
        success: function(data) {
            //do something
            progress = null;
        }
    });
}

5

私はこれが少し遅れる可能性があることを知っていますが、abortメソッドを呼び出しても実際にはリクエストが中止されないという同様の問題が発生します。代わりに、ブラウザーはまだ使用しない応答を待っていました。このコードはその問題を解決しました。

 try {
        xhr.onreadystatechange = null;
        xhr.abort();
} catch (e) {}

1

なぜリクエストを中止する必要があるのですか?

各リクエストに5秒以上かかる場合、どうなりますか?

リクエストとともに渡されるパラメータが変更されていない場合は、リクエストを中止しないでください。例:-リクエストは通知データを取得するためのものです。このような状況では、以前のAjaxリクエストが完了した後にのみ新しいリクエストを設定するという優れたアプローチがあります。

$(document).ready(

    var fn = function(){

        $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            },

            complete: function(){setTimeout(fn, 500);}
        });
    };

     var interval = setTimeout(fn, 500);

);

5
これは悪い考えです。新しい呼び出しを開始するときに、前の呼び出しのcompleteイベントが発生しないようにする必要があります。このアプローチでは、非常に奇妙な結果になる可能性があります。
Webberig 2014

1

jquery-validate.jsを使用できます。以下は、jquery-validate.jsからのコードスニペットです。

// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()

var pendingRequests = {},
    ajax;
// Use a prefilter if available (1.5+)
if ( $.ajaxPrefilter ) {
    $.ajaxPrefilter(function( settings, _, xhr ) {
        var port = settings.port;
        if ( settings.mode === "abort" ) {
            if ( pendingRequests[port] ) {
                pendingRequests[port].abort();
            }
            pendingRequests[port] = xhr;
        }
    });
} else {
    // Proxy ajax
    ajax = $.ajax;
    $.ajax = function( settings ) {
        var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
            port = ( "port" in settings ? settings : $.ajaxSettings ).port;
        if ( mode === "abort" ) {
            if ( pendingRequests[port] ) {
                pendingRequests[port].abort();
            }
            pendingRequests[port] = ajax.apply(this, arguments);
            return pendingRequests[port];
        }
        return ajax.apply(this, arguments);
    };
}

そのため、ajaxリクエストを行うときにパラメーターモード中止するように設定するだけで済みます。

参照:https : //cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.14.0/jquery.validate.js


0

jQuery:これを出発点として、インスピレーションとして使用してください。私はそれを次のように解決しました:(これは完璧な解決策ではなく、最後のインスタンスを中止し、WIPコードです)

var singleAjax = function singleAjax_constructor(url, params) {
    // remember last jQuery's get request
    if (this.lastInstance) {
        this.lastInstance.abort();  // triggers .always() and .fail()
        this.lastInstance = false;
    }

    // how to use Deferred : http://api.jquery.com/category/deferred-object/
    var $def = new $.Deferred();

    // pass the deferrer's request handlers into the get response handlers
    this.lastInstance = $.get(url, params)
        .fail($def.reject)         // triggers .always() and .fail()
        .success($def.resolve);    // triggers .always() and .done()

    // return the deferrer's "control object", the promise object
    return $def.promise();
}


// initiate first call
singleAjax('/ajax.php', {a: 1, b: 2})
    .always(function(a,b,c) {console && console.log(a,b,c);});

// second call kills first one
singleAjax('/ajax.php', {a: 1, b: 2})
    .always(function(a,b,c) {console && console.log(a,b,c);});
    // here you might use .always() .fail() .success() etc.

0

APIを呼び出す関数を作成します。この関数内でリクエストを定義しcallApiRequest = $.get(...ます。これは変数の定義ですが、リクエストはすぐに呼び出されますが、今はリクエストが変数として定義されています。リクエストが呼び出される前に、変数が定義されているかどうか、typeof(callApiRequest) != 'undefined'および保留中かどうかを確認します。suggestCategoryRequest.state() == 'pending'両方がtrueの場合.abort()、リクエストが成功コールバックの実行を妨げます。

// We need to wrap the call in a function
callApi = function () {

    //check if request is defined, and status pending
    if (typeof(callApiRequest) != 'undefined'
        && suggestCategoryRequest.state() == 'pending') {

        //abort request
        callApiRequest.abort()

    }

    //define and make request
    callApiRequest = $.get("https://example.com", function (data) {

        data = JSON.parse(data); //optional (for JSON data format)
        //success callback

    });
}

サーバー/ APIはリクエストの中止をサポートしていない可能性があります(APIがすでにいくつかのコードを実行した場合はどうなりますか)が、JavaScriptコールバックは起動しません。これは、たとえばハッシュタグの入力など、ユーザーに入力候補を提供する場合に役立ちます。

エラーコールバックの定義を追加することにより、この関数をさらに拡張できます-要求が中止された場合にどうなるか。

このスニペットの一般的なユースケースは、keypressイベントで発生するテキスト入力です。タイムアウトを使用して、キャンセルする必要があるリクエストの一部を送信しないようにすることができます.abort()


-7

また、readyState 0もチェックする必要があります。xhr.abort()を使用すると、このオブジェクトでreadyStateが0に設定され、ifチェックが常にtrueになるため、readyState!= 4

$(document).ready(
    var xhr;

    var fn = function(){
        if(xhr && xhr.readyState != 4 && xhr.readyState != 0){
            xhr.abort();
        }
        xhr = $.ajax({
            url: 'ajax/progress.ftl',
            success: function(data) {
                //do something
            }
        });
    };

    var interval = setInterval(fn, 500);
); 

2
アルンの答えをコピーして貼り付けましたか?そのためには、まったく同じであることの間隔と、すべての...のような2つのコード・ブロックの可能性

@ user2700923彼の投稿はまったく同じではありません。彼のポイントは、readyState 0もチェックする必要があるということです。しかし、これはArunの回答へのコメントとしてより適切でした。
Stefan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.