jQuery에서 모든 활성 아약스 요청 중지


216

양식을 제출할 때 모든 활성 아약스 요청이 실패하고 문제가 발생하는 문제가 있습니다.

Trigerring 오류 이벤트없이 jQuery에서 모든 활성 Ajax 요청을 중지하는 방법은 무엇입니까?

답변:


273

ajax 요청을 작성할 때마다 변수를 사용하여 저장할 수 있습니다.

var request = $.ajax({
    type: 'POST',
    url: 'someurl',
    success: function(result){}
});

그런 다음 요청을 중단 할 수 있습니다.

request.abort();

배열을 사용하여 보류중인 모든 아약스 요청을 추적하고 필요한 경우 중단 할 수 있습니다.


THX, 동시에 여러 요청을 사용했기 때문에 FLAG를 추가했습니다
jcho360

여기에 간단한 작업의 예는 다음과 같습니다 stackoverflow.com/a/42312101/3818394
다르 메쉬 파텔

함수에 아약스 호출이 있는데 어떻게 중단 할 수 있습니까?
Kalariya_M

아약스 호출이 진행 중일 때 다른 함수에서 변수에 액세스하려면 변수를 전역으로 선언해야합니다. 예 : 다중 파일 업로드 프로세스
Clain Dsilva

180

다음 스 니펫을 사용하면 요청 목록 ( ) 을 유지 관리하고 필요한 경우 모두 중단 할 수 있습니다. 다른 AJAX 호출을 하기 전에<HEAD> html 에 배치하는 것이 가장 좋습니다.

<script type="text/javascript">
    $(function() {
        $.xhrPool = [];
        $.xhrPool.abortAll = function() {
            $(this).each(function(i, jqXHR) {   //  cycle through list of recorded connection
                jqXHR.abort();  //  aborts connection
                $.xhrPool.splice(i, 1); //  removes from list by index
            });
        }
        $.ajaxSetup({
            beforeSend: function(jqXHR) { $.xhrPool.push(jqXHR); }, //  annd connection to list
            complete: function(jqXHR) {
                var i = $.xhrPool.indexOf(jqXHR);   //  get index for current connection completed
                if (i > -1) $.xhrPool.splice(i, 1); //  removes from list by index
            }
        });
    })
</script>

2
@ mkmurray-IE8에서 초기화하면 얻을 것 같습니다 Object doesn't support property or method 'indexOf'. stackoverflow.com/a/2608601/181971 이거나 아마도 stackoverflow.com/a/2608618/181971로 교체 될 수 있습니까?
Tim

3
@grr이 맞습니다. 그의 답변을 확인하고 ajaxSetup 문서를 확인하십시오 .
kzfabi

@Tim-Steven이 제안한대로 var index = $ .xhrPool.indexOf (jqXHR); 사용 : var index = $ .inArray (jqXHR, $ .xhrPool);
Christopher

1
@ mkmurray : TypeError를 보여줍니다 : jqXHR.abort는 나를위한 기능이 아닙니다. :(
Shesha

abortAll 메소드에 약간의 논리적 오류가 있습니다.이 답변은 여기에서 수정되었습니다. stackoverflow.com/a/45500874/1041341
Sarin JS

122

문서 페이지에 표시된대로 ajaxSetup 사용이 올바르지 않습니다 . 기본값 만 설정하고 일부 요청이 재정의하면 엉망이됩니다.

나는 파티에 늦었지만 나중에 누군가가 같은 문제에 대한 해결책을 찾고 있다면 나중에 참조 할 것입니다. 이전 답변에서 영감을 얻었으며 이전 답변과 거의 동일하지만 더 완벽합니다.

// Automatically cancel unfinished ajax requests 
// when the user navigates elsewhere.
(function($) {
  var xhrPool = [];
  $(document).ajaxSend(function(e, jqXHR, options){
    xhrPool.push(jqXHR);
  });
  $(document).ajaxComplete(function(e, jqXHR, options) {
    xhrPool = $.grep(xhrPool, function(x){return x!=jqXHR});
  });
  var abort = function() {
    $.each(xhrPool, function(idx, jqXHR) {
      jqXHR.abort();
    });
  };

  var oldbeforeunload = window.onbeforeunload;
  window.onbeforeunload = function() {
    var r = oldbeforeunload ? oldbeforeunload() : undefined;
    if (r == undefined) {
      // only cancel requests if there is no prompt to stay on the page
      // if there is a prompt, it will likely give the requests enough time to finish
      abort();
    }
    return r;
  }
})(jQuery);

다른 함수에서 abort () 메서드를 어떻게 호출합니까?
Stan James

중단은 방법이 아니라 함수입니다. 일반적으로 동일한 캡슐화 내에서 호출합니다. 캡슐화 외부에서 사용해야하는 경우 함수 이름 전에 "var"을 제거하면 전 세계에서 사용 가능한 기능이됩니다
Trey

안녕하세요, r이 언제 정의되지 않을지 누군가 설명 할 수 있습니까?
Varun

36

다음은 현재이를 달성하기 위해 사용하고있는 것입니다.

$.xhrPool = [];
$.xhrPool.abortAll = function() {
  _.each(this, function(jqXHR) {
    jqXHR.abort();
  });
};
$.ajaxSetup({
  beforeSend: function(jqXHR) {
    $.xhrPool.push(jqXHR);
  }
});

참고 : _.each of underscore.js가 있지만 반드시 필요한 것은 아닙니다. 나는 단지 게으르고 $ .each ()로 바꾸고 싶지 않습니다. 8P


2
방금 게시하려고하는 약간 수정 된 솔루션이 있습니다.
mkmurray

7
메모리 누수가 발생합니다. aboutAll배열에서 요소를 제거해야합니다. 또한 요청이 완료되면 목록에서 자신을 제거해야합니다.
Behrang Saeedzadeh

5
@BehrangSaeedzadeh 또한 개선 된 버전을 게시해야합니다.
mattsven

19

각 xhr 요청에 고유 ID를 부여하고 전송하기 전에 오브젝트에 오브젝트 참조를 저장하십시오. xhr 요청이 완료된 후 참조를 삭제하십시오.

언제든지 모든 요청을 취소하려면

$.ajaxQ.abortAll();

취소 된 요청의 고유 ID를 반환합니다. 테스트 목적으로 만 사용하십시오.

작업 기능 :

$.ajaxQ = (function(){
  var id = 0, Q = {};

  $(document).ajaxSend(function(e, jqx){
    jqx._id = ++id;
    Q[jqx._id] = jqx;
  });
  $(document).ajaxComplete(function(e, jqx){
    delete Q[jqx._id];
  });

  return {
    abortAll: function(){
      var r = [];
      $.each(Q, function(i, jqx){
        r.push(jqx._id);
        jqx.abort();
      });
      return r;
    }
  };

})();

필요할 때 더 많은 기능을 추가하는 데 사용할 수있는 단일 함수를 가진 객체를 반환합니다.


17

여러 요청에 너무 쉽다는 것을 알았습니다.

1 단계 : 페이지 상단에 변수를 정의하십시오.

  xhrPool = []; // no need to use **var**

2 단계 : 모든 ajax 요청에서 beforeSend를 설정하십시오.

  $.ajax({
   ...
   beforeSend: function (jqXHR, settings) {
        xhrPool.push(jqXHR);
    },
    ...

3 단계 : 필요한 곳에서 사용하십시오 :

   $.each(xhrPool, function(idx, jqXHR) {
          jqXHR.abort();
    });

이는 stackoverflow.com/a/6618288/1772379 와 마찬가지로 메모리가 누출 되며 정확히 같은 이유로 인해 메모리가 누수됩니다 .
벤 존슨

JavaScript를 작성하는 정말 끔찍한 방법입니다.
Ozil

1
마지막에 xhrPool 배열을 지우거나 비울 수 있습니다
공간 지구

6

xhrPool.abortAll 이 주어진 URL의 보류중인 모든 요청 중단 할 수 있도록 mkmurray 및 SpYk3HH 답변을 위에서 확장했습니다 .

$.xhrPool = [];
$.xhrPool.abortAll = function(url) {
    $(this).each(function(i, jqXHR) { //  cycle through list of recorded connection
        console.log('xhrPool.abortAll ' + jqXHR.requestURL);
        if (!url || url === jqXHR.requestURL) {
            jqXHR.abort(); //  aborts connection
            $.xhrPool.splice(i, 1); //  removes from list by index
        }
    });
};
$.ajaxSetup({
    beforeSend: function(jqXHR) {
        $.xhrPool.push(jqXHR); //  add connection to list
    },
    complete: function(jqXHR) {
        var i = $.xhrPool.indexOf(jqXHR); //  get index for current connection completed
        if (i > -1) $.xhrPool.splice(i, 1); //  removes from list by index
    }
});
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
    console.log('ajaxPrefilter ' + options.url);
    jqXHR.requestURL = options.url;
});

abortAll이 URL을 매개 변수로 선택적으로 승인 할 수 있고 해당 URL에 대한 보류중인 호출 만 취소한다는 점을 제외하면 사용법은 동일합니다.


5

앤디의 코드에 문제가 있었지만 훌륭한 아이디어를 얻었습니다. 첫 번째 문제는 성공적으로 완료된 jqXHR 객체를 제거해야한다는 것입니다. 또한 abortAll 함수를 수정해야했습니다. 최종 작업 코드는 다음과 같습니다.

$.xhrPool = [];
$.xhrPool.abortAll = function() {
            $(this).each(function(idx, jqXHR) {
                        jqXHR.abort();
                        });
};
$.ajaxSetup({
    beforeSend: function(jqXHR) {
            $.xhrPool.push(jqXHR);
            }
});
$(document).ajaxComplete(function() {
            $.xhrPool.pop();
            });

나는 일을하는 ajaxComplete () 방법을 좋아하지 않았다. .ajaxSetup 구성 방법에 관계없이 작동하지 않습니다.


7
특정 순서로 완료되지 않으면 잘못된 요청으로 팝을 호출 할 수 있다고 생각합니까?
jjmontes

1
예, 팝 대신 슬라이스를하고 싶습니다. 게시하려고하는 약간 수정 된 솔루션이 있습니다.
mkmurray

4

나는 그것이 나를 위해 작동하도록 코드를 업데이트했습니다

$.xhrPool = [];
$.xhrPool.abortAll = function() {
    $(this).each(function(idx, jqXHR) {
        jqXHR.abort();
    });
    $(this).each(function(idx, jqXHR) {
        var index = $.inArray(jqXHR, $.xhrPool);
        if (index > -1) {
            $.xhrPool.splice(index, 1);
        }
    });
};

$.ajaxSetup({
    beforeSend: function(jqXHR) {
        $.xhrPool.push(jqXHR);
    },
    complete: function(jqXHR) {
        var index = $.inArray(jqXHR, $.xhrPool);
        if (index > -1) {
            $.xhrPool.splice(index, 1);
        }
    }
});

4

내 모자를 던지기. 배열 에 대한 오퍼 abortremove메소드 xhrPool이며 ajaxSetup대체 에 문제가 발생하지 않습니다 .

/**
 * Ajax Request Pool
 * 
 * @author Oliver Nassar <onassar@gmail.com>
 * @see    http://stackoverflow.com/questions/1802936/stop-all-active-ajax-requests-in-jquery
 */
jQuery.xhrPool = [];

/**
 * jQuery.xhrPool.abortAll
 * 
 * Retrieves all the outbound requests from the array (since the array is going
 * to be modified as requests are aborted), and then loops over each of them to
 * perform the abortion. Doing so will trigger the ajaxComplete event against
 * the document, which will remove the request from the pool-array.
 * 
 * @access public
 * @return void
 */
jQuery.xhrPool.abortAll = function() {
    var requests = [];
    for (var index in this) {
        if (isFinite(index) === true) {
            requests.push(this[index]);
        }
    }
    for (index in requests) {
        requests[index].abort();
    }
};

/**
 * jQuery.xhrPool.remove
 * 
 * Loops over the requests, removes it once (and if) found, and then breaks out
 * of the loop (since nothing else to do).
 * 
 * @access public
 * @param  Object jqXHR
 * @return void
 */
jQuery.xhrPool.remove = function(jqXHR) {
    for (var index in this) {
        if (this[index] === jqXHR) {
            jQuery.xhrPool.splice(index, 1);
            break;
        }
    }
};

/**
 * Below events are attached to the document rather than defined the ajaxSetup
 * to prevent possibly being overridden elsewhere (presumably by accident).
 */
$(document).ajaxSend(function(event, jqXHR, options) {
    jQuery.xhrPool.push(jqXHR);
});
$(document).ajaxComplete(function(event, jqXHR, options) {
    jQuery.xhrPool.remove(jqXHR);
});

2

모든 아약스 요청의 풀을 만들고 중단하십시오 .....

var xhrQueue = []; 

$(document).ajaxSend(function(event,jqxhr,settings){
    xhrQueue.push(jqxhr); //alert(settings.url);
});

$(document).ajaxComplete(function(event,jqxhr,settings){
    var i;   
    if((i=$.inArray(jqxhr,xhrQueue)) > -1){
        xhrQueue.splice(i,1); //alert("C:"+settings.url);
    }
});

ajaxAbort = function (){  //alert("abortStart");
    var i=0;
    while(xhrQueue.length){ 
        xhrQueue[i++] .abort(); //alert(i+":"+xhrQueue[i++]);
    }
};

1

독립 코드를 사용하는 것이 좋습니다 .....

var xhrQueue = []; 

$(document).ajaxSend(function(event,jqxhr,settings){
    xhrQueue.push(jqxhr); //alert(settings.url);
});

$(document).ajaxComplete(function(event,jqxhr,settings){
    var i;   
    if((i=$.inArray(jqxhr,xhrQueue)) > -1){
        xhrQueue.splice(i,1); //alert("C:"+settings.url);
    }
});

ajaxAbort = function (){  //alert("abortStart");
    var i=0;
    while(xhrQueue.length){ 
        xhrQueue[i++] .abort(); //alert(i+":"+xhrQueue[i++]);
    }
};

0

마찬가지로 중요한 것은 로그 오프하고 타이머를 사용하여 새 요청을 생성한다고 가정하십시오. 세션 데이터는 각각의 새로운 부트 스트랩으로 갱신되기 때문에 (Drupal과 대화하고 있다고 말할 수 있지만 세션을 사용하는 모든 사이트가 될 수 있습니다.) 나는 모든 스크립트를 검색하고 교체해야했고, 다른 경우에 많은 것들이 실행되었습니다.

var ajReq = [];
var canAj = true;
function abort_all(){
 for(x in ajReq){
    ajReq[x].abort();
    ajReq.splice(x, 1)
 }
 canAj = false;
}
function rmvReq(ranNum){
 var temp = [];
 var i = 0;
 for(x in ajReq){
    if(x == ranNum){
     ajReq[x].abort();
     ajReq.splice(x, 1);
    }
    i++;
 }
}
function randReqIndx(){
 if(!canAj){ return 0; }
 return Math.random()*1000;
}
function getReqIndx(){
 var ranNum;
 if(ajReq.length){
    while(!ranNum){
     ranNum = randReqIndx();
     for(x in ajReq){
    if(x===ranNum){
     ranNum = null;
    }
     }
    }
    return ranMum;
 }
 return randReqIndx();
}
$(document).ready(function(){
 $("a").each(function(){
    if($(this).attr('href').indexOf('/logout')!=-1){          
     $(this).click(function(){
    abort_all();                 
     });
    }
 })
});
// Then in all of my scripts I wrapped my ajax calls... If anyone has a suggestion for a 
    // global way to do this, please post
var reqIndx = getReqIndx();
if(reqIndx!=0){
ajReq[reqIndx] = $.post(ajax, { 'action': 'update_quantities', iids:iidstr, qtys:qtystr },  
function(data){
 //..do stuff
 rmvReq(reqIndx);
 },'json');
}

0
var Request = {
    List: [],
    AbortAll: function () {
        var _self = this;
        $.each(_self.List, (i, v) => {
            v.abort();
        });
    }
}
var settings = {
    "url": "http://localhost",
    success: function (resp) {
        console.log(resp)
    }
}

Request.List.push($.ajax(settings));

모든 아약스 요청을 중단 할 때 마다이 라인에 전화하면됩니다.

Request.AbortAll()

-2

모든 아약스 요청을 중단하는 데 사용하는 더미 솔루션이 있습니다. 이 솔루션은 전체 페이지를 다시로드합니다. 이 솔루션은 각 ajax 요청에 ID를 지정하지 않고 for-loop 내에서 ajax 요청을하는 경우에 좋습니다. 그러면 모든 아약스 요청이 종료됩니다.

location.reload();

-3

클릭 한 번으로 연결하는 방법은 다음과 같습니다 (페이지가 많은 AJAX 호출을하고 있고 다른 곳으로 이동하려는 경우에 유용합니다).

$ ->
    $.xhrPool = [];

$(document).ajaxSend (e, jqXHR, options) ->
    $.xhrPool.push(jqXHR)

$(document).ajaxComplete (e, jqXHR, options) ->
    $.xhrPool = $.grep($.xhrPool, (x) -> return x != jqXHR);

$(document).delegate 'a', 'click', ->
    while (request = $.xhrPool.pop())
      request.abort()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.