모든 jQuery Ajax 요청이 완료 될 때까지 기다리시겠습니까?


675

모든 jQuery Ajax 요청이 다른 함수 내에서 완료 될 때까지 함수를 기다리려면 어떻게해야합니까?

즉, 다음을 실행하기 전에 모든 Ajax 요청이 완료 될 때까지 기다려야합니다. 그러나 어떻게?


원래 아약스 요청을 어떻게 호출합니까?
NakedBrunch

2
"완료"는 무슨 뜻입니까? "모든 요청이 성공적으로 완료되었거나 완료되지 않았습니다"(해결 또는 거부)로 이해합니다. 그러나 "모든 요청이 성공적으로 완료되었습니다"(해결됨)를 의미 할 수 있습니다. api.jquery.com/category/deferred-object의
Adrien Be

답변:


911

jQuery는 이제이 목적을위한 when 함수 를 정의합니다 .

임의의 수의 Deferred 객체를 인수로 받아들이고 모든 객체가 해결되면 함수를 실행합니다.

즉, 네 개의 ajax 요청을 시작하고 (예를 들어) 완료 될 때 조치를 수행하려는 경우 다음과 같이 수행 할 수 있습니다.

$.when(ajax1(), ajax2(), ajax3(), ajax4()).done(function(a1, a2, a3, a4){
    // the code here will be executed when all four ajax requests resolve.
    // a1, a2, a3 and a4 are lists of length 3 containing the response text,
    // status, and jqXHR object for each of the four ajax calls respectively.
});

function ajax1() {
    // NOTE:  This function must return the value 
    //        from calling the $.ajax() method.
    return $.ajax({
        url: "someUrl",
        dataType: "json",
        data:  yourJsonData,            
        ...
    });
}

제 생각에는 깨끗하고 명확한 구문을 만들고 페이지가 개발 될 때 원하지 않는 부작용을 일으킬 수있는 ajaxStart 및 ajaxStop과 같은 전역 변수를 사용하지 마십시오.

얼마나 많은 아약스 인수를 기다려야하는지 모르는 경우 (즉, 가변 개수의 인수를 사용하려는 경우) 여전히 수행 할 수 있지만 조금 까다 롭습니다. 참조 ) $ .when (에 Deferreds의 배열에서 패스를 (그리고 아마도 jQuery를 .when 문제 해결 인수의 변수 번호 ).

ajax 스크립트 등의 실패 모드에 대한 심도있는 제어가 필요한 경우 반환 된 객체를 저장할 수 있습니다 . 원래의 모든 ajax 쿼리를 포함 .when()하는 jQuery Promise 객체입니다. 자세한 성공 / 실패 처리기를 추가하기 위해 .then()또는 전화를 걸 수 있습니다 .fail().


46
간단하고 효율적이며 훌륭하게 작동하기 때문에 정답으로 표시해야합니다. 또한 더 유용한 메소드뿐만 아니라 더 유용한 메소드를 갖는 오브젝트를 $.when리턴 한다는 점에 유의해야 합니다 . 예를 들어, 메소드를 사용하면 두 요청이 모두 성공하거나 하나 이상의 요청이 실패 할 때 반응 할 수 있습니다. Promise.done.then(onSuccess, onFailure)
skalee

2
요청 ajax1..4를 배열로 묶어서 전달할 수 있습니까?
andig

33
fail사건에 주의하십시오 . 달리 done, fail즉시에 화재가 먼저 실패하고 무시 나머지 deferreds.
Ryan Mohr

1
@skalee onFailure함수를 첨부 할 수 있다는 사실을 강조해 주셔서 감사합니다 . OP의 질문에 대한 의견에서 지적한 바와 같이, 그는 "완료"의 의미를보다 정확하게 나타내기를 원할 수 있습니다. "라이언 모어"도 있다는 사실에 대해 매우 좋은 점을 가지고 않았다 fail동작합니다 다르게 등 done에 대해, 일부 추가 읽기를 수행 할 Promises것 같아요 html5rocks.com/en/tutorials/es6/promises을
아드 리앙은 수

1
사람들에게 when 메소드를 제공하고 일반적으로 약속하는 것이 좋지만, 이것이 최선의 대답은 아니라고 생각합니다. 이러한 아약스 기능 중 하나라도 라인 아래에서 다른 아약스 요청을 만든 다음 체인에 새 약속을 올바르게 통합하지 않으면 해당 요청이이 기술을 벗어날 것입니다. 예를 들어, '약속적인'방식으로 작성되지 않았고 생성 한 xhr 객체를 반환하지 않기 때문에 ajax add-to-cart 동작에 사용중인 Shopify 라이브러리를 수정하지 않고이 기술을 사용할 수 없습니다. 이게 말이 되요? 그래도 여전히 좋은 대답입니다!
Ziggy

292

문서에서 모든 ajax 요청이 완료된 시기 를 알고 싶다면 그 수에 관계없이 $ .ajaxStop 이벤트를 다음과 같이 사용하십시오 .

$(document).ajaxStop(function () {
  // 0 === $.active
});

이 경우, 애플리케이션에서 몇 개의 요청이 발생하고 있는지, 나중에 완료 될지, 복잡한 논리를 파헤 치거나 어떤 기능이 HTTP(S)요청을 수행 중인지 찾을 필요도 없습니다 .

$.ajaxStop여기서 HTMLrequst에 의해 수정 될 것으로 생각 되는 모든 노드에 바인딩 될 수도 있습니다.


업데이트 : 구문
을 고수 ES하려면 알려진 방법에 Promise.all 을 사용할 수 있습니다 ajax.

Promise.all([ajax1(), ajax2()]).then(() => {
  // all requests finished successfully
}).catch(() => {
  // all requests finished but one or more failed
})

여기서 흥미로운 점은 함께 모두 작동한다는 것입니다 Promises$.ajax요청.

다음은 jsFiddle 데모입니다.


업데이트 2 : async / await 구문을
사용하는 최신 버전 :

try {
  const results = await Promise.all([ajax1(), ajax2()])
  // do other actions
} catch(ex) { }

16
+1 익명 콜백 / 클로저로 타사 스크립트를 처리해야하는 경우 다른 답변보다 훨씬 낫습니다 .
카이저

5
@kaiser 유효한 요점이지만 질문이 묻는 것이 아닙니다. 모든 AJAX 호출이 돌아 오기를 기다리지 않으려면 좋지 않습니다. 이 질문은 당신이 직접 작성한 AJAX 호출을 기다리는 것에 관한 것입니다 (OP가 쓴 것처럼 다른 함수 내에서 호출 됨). 다른 코드로 인해 원하지 않는 다른 AJAX 호출이있을 수 있습니다.
Juan Mendes

6
when () 솔루션과 비교하여 ajax 호출 수를 알 수없는 경우에도 작동하는 이점이 있습니다.
Alexis Dufrenoy

5
when () 솔루션과 비교할 때 문서 전체의 전역 상태를 공유하므로 다른 구성 요소와 함께 작동하지 않는 것이 큰 단점이 있습니다. 긴 폴링이 지속적으로 진행되면 절대로 실행되지 않을 수도 있습니다.
Bergi

3
당신은 정확하지 @AdrienBe이 ajaxStop 그들이 내 말의 증명이 보는 것처럼, 성공하지 않거나에 상관없이 모든 아약스 요청을 처리하지있어 jsfiddle.net/36votxba/2
아르센 Khachaturyan

32

내가 찾은 좋은 답변 에 의한 gnarf 내가 찾던 정확히 내 자신을 :)

jQuery ajaxQueue

//This handles the queues    
(function($) {

  var ajaxQueue = $({});

  $.ajaxQueue = function(ajaxOpts) {

    var oldComplete = ajaxOpts.complete;

    ajaxQueue.queue(function(next) {

      ajaxOpts.complete = function() {
        if (oldComplete) oldComplete.apply(this, arguments);

        next();
      };

      $.ajax(ajaxOpts);
    });
  };

})(jQuery);

그런 다음 다음과 같이 대기열에 ajax 요청을 추가 할 수 있습니다.

$.ajaxQueue({
        url: 'page.php',
        data: {id: 1},
        type: 'POST',
        success: function(data) {
            $('#status').html(data);
        }
    });

37
이 답변에 대한 적절한 기여를 잊어 버린 것 같습니다 . 추가했습니다.
Tim Post

21

ajaxStop이벤트를 사용하십시오 .

예를 들어 100 개의 아약스 요청을 가져 오는 동안 loading ... 메시지가 있고 일단로드 된 메시지를 숨기려고한다고 가정 해 봅시다 .

jQuery 문서에서 :

$("#loading").ajaxStop(function() {
  $(this).hide();
});

해당 페이지에서 모든 ajax 요청이 완료 될 때까지 기다립니다.


5
이것은 페이지에 다른 AJAX 요청이 없다는 것을 알고 있다고 가정합니다. 아주 좋은 가정은 아닙니다.
Juan Mendes

jQuery 1.8부터 .ajaxStop () 메소드는 문서에만 첨부해야합니다.
Geomorillo

1
내가 틀렸다면 수정하되 프로젝트가 "오래된 학교 웹 양식"사이트로 바뀌지 않습니까? 전체 페이지가 요청을 기다려야 계속 진행할 수 있다면 아약스 요청의 요점은 무엇입니까?
BillRuhl

우리의 경우 @BillRuhl에서 jquery 컬렉션을 반복하여 새로운 것을 만들고 레이아웃이 조정되기 전에 전체 컬렉션에 대해 알아야합니다. 특별한 경우는 아닌 것 같습니다. 다른 많은 아약스 작업이 진행 중이라면 좋지 않을 수 있지만 여기서는 그렇지 않습니다.
eon

21

참고 : 위 답변은이 답변을 작성할 당시 존재하지 않은 기능을 사용합니다. jQuery.when()이 접근법 대신에 사용 하는 것이 좋지만 역사적인 목적으로 답을 남기고 있습니다.

-

구현 방법은 코드에 따라 다르지만 간단한 카운팅 세마포어로 해결할 수도 있습니다. 간단한 예는 다음과 같습니다.

var semaphore  = 0,     // counting semaphore for ajax requests
    all_queued = false; // bool indicator to account for instances where the first request might finish before the second even starts

semaphore++;
$.get('ajax/test1.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test2.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test3.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

semaphore++;
$.get('ajax/test4.html', function(data) {
    semaphore--;
    if (all_queued && semaphore === 0) {
        // process your custom stuff here
    }
});

// now that all ajax requests are queued up, switch the bool to indicate it
all_queued = true;

{async : false}와 같이 작동하지만 브라우저를 잠그고 싶지 않은 경우 jQuery 대기열을 사용하여 동일한 작업을 수행 할 수 있습니다.

var $queue = $("<div/>");
$queue.queue(function(){
    $.get('ajax/test1.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test2.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test3.html', function(data) {
        $queue.dequeue();
    });
}).queue(function(){
    $.get('ajax/test4.html', function(data) {
        $queue.dequeue();
    });
});

10
이것은 사소한 문제를 지나치게 복잡하게하는 것처럼 보입니다.
크리스

2
그다지 복잡하지는 않습니다. 세마포어 계산은 CS에서 일반적인 메커니즘입니다. 그래도 원하는 경우 jQuery 대기열을 사용하는 예제는 세마포어를 직접 구현하지 않고도 잘 작동합니다.
BBonifield

1
세마포 카운터에는 문제가 없지만 결과 콜백을 처리하기 위해 FOUR 함수가 있다는 아이디어에는 문제가 있습니다. 먼저 함수를 정의한 다음 각 함수에서 해당 함수를 참조해야합니다 .get(). 그렇게하면 최소한 그 코드를 복제하지 마십시오. 뿐만 아니라 function(){}매번 선언하면 매번 메모리가 할당됩니다! 정적으로 정의 된 함수를 호출 할 수 있다면 나쁜 습관입니다.
Alexis Wilke

1
@AlexisWilke 이것은 4.5 년 된 답변이며 세마포어 및 큐가 작동하는 방법의 예입니다. 당신은 이것에 대해 너무 열심히 생각하고 있으며, 포인트를 만들기 위해 대문자 화가 필요하다고 생각하지 않습니다.
BBonifield

2
글쎄 ... 난 당신에게 -1을 준 사람이 아니에요 ... 나는 대답이 노화하는 경향이 있음을 이해합니다. 그러나 사람들은 계속해서 그것들을 찾고 있으며, 내가 아는 한 오늘날에도 여전히 그들을 이용할 사람들에게 정보를 제공하는 것은 금지되어 있지 않습니다.
Alexis Wilke

8

자바 스크립트는 이벤트 기반이므로 기다리지 말고 후크 / 콜백을 설정하십시오.

아마도 성공 / 완료 방법을 사용할 수 있습니다. jquery.ajax

또는 .ajaxComplete를 사용할 수 있습니다 .

$('.log').ajaxComplete(function(e, xhr, settings) {
  if (settings.url == 'ajax/test.html') {
    $(this).text('Triggered ajaxComplete handler.');
    //and you can do whatever other processing here, including calling another function...
  }
});

비록 당신은 당신의 아약스 요청이 어떻게 더 정확하게 호출되는지에 대한 의사 코드를 게시해야하지만 ...


8

약간의 해결 방법은 다음과 같습니다.

// Define how many Ajax calls must be done
var ajaxCalls = 3;
var counter = 0;
var ajaxCallComplete = function() {
    counter++;
    if( counter >= ajaxCalls ) {
            // When all ajax calls has been done
        // Do something like hide waiting images, or any else function call
        $('*').css('cursor', 'auto');
    }
};

var loadPersons = function() {
        // Show waiting image, or something else
    $('*').css('cursor', 'wait');

    var url = global.ctx + '/loadPersons';
    $.getJSON(url, function(data) {
            // Fun things
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCountries = function() {
    // Do things
    var url = global.ctx + '/loadCountries';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

var loadCities = function() {
    // Do things
    var url = global.ctx + '/loadCities';
    $.getJSON(url, function(data) {
            // Travels
    })
    .complete(function() { **ajaxCallComplete();** });
};

$(document).ready(function(){
    loadPersons();
    loadCountries();
    loadCities();
});

희망은 도움이 될 수 있습니다 ...


다른 답변은 이해하기 쉽기 때문에 기술적으로 더 좋지만, 나는 이것을 정말로 좋아합니다. 좋은!
Jay

4

jQuery를 사용하면 ajax 요청을 비동기로할지 여부를 지정할 수 있습니다. 단순히 ajax 요청을 동기식으로 만들면 나머지 코드는 반환 될 때까지 실행되지 않습니다.

예를 들면 다음과 같습니다.

jQuery.ajax({ 
    async: false,
    //code
});

42
{async : false}를 사용하면 브라우저가 일시적으로 잠길 수 있습니다. api.jquery.com/jQuery.ajax
BBonifield

30
이것은 표준 jQuery / Javascript 실습과 상반됩니다. AJAX는 항상 비동기식이어야합니다. 대신 jQuery.when ()을 사용해야합니다.
SystemParadox

43
정말 나쁜 생각입니다! 절대 그렇게하지 마십시오 ! 블로킹 = 사용자 행동에 전혀 반응하지 않으며, 스크롤 또는 기타에도 반응하지 않습니다! (또한 async : false는 jQuery 1.8에서 더 이상 사용되지 않습니다.)
skalee

5
특히, 예상치 못한 이유로 요청이 실패하거나 오랜 시간이 걸리는 경우 (머피의 법칙에 따라 발생할 수 있습니다!) 이는 위에서 언급 한대로 브라우저 잠금으로 인해 프로덕션 코드에 좋지 않은 아이디어입니다.
Alex

27
이것은 끔찍한 나쁜 생각입니다. 이 답변을 사용하지 마십시오.
Tauren

2

간단한 것이 필요하다면; 한 번 및 콜백 완료

        //multiple ajax calls above
        var callback = function () {
            if ($.active !== 0) {
                setTimeout(callback, '500');
                return;
            }
            //whatever you need to do here
            //...
        };
        callback();

4
무한 루프를 생성 할 수 있습니다!
Diego Favero 2019

2
이것은 끝없는 루프입니까? 언제? 언제 AJAX가 반환되지 않습니까?
조나단

2

또한 async.js 사용할 수 있습니다 .

시간 초과, SqlLite 호출 등과 같은 약속을 지원하지 않는 모든 종류의 비동기 호출을 단순히 아약스 요청뿐만 아니라 병합 할 수 있기 때문에 $ .w보다 낫습니다.


2

@BBonifield 답변을 기반으로 세마포어 논리가 모든 아약스 호출에 확산되지 않도록 유틸리티 함수를 작성했습니다.

untilAjax 모든 ajaxCall이 완료되면 콜백 함수를 호출하는 유틸리티 함수입니다.

ajaxObjs 아약스 설정 객체의 배열입니다 [http://api.jquery.com/jQuery.ajax/] .

fn 콜백 함수입니다

function untilAjax(ajaxObjs, fn) {
  if (!ajaxObjs || !fn) {
    return;
  }
  var ajaxCount = ajaxObjs.length,
    succ = null;

  for (var i = 0; i < ajaxObjs.length; i++) { //append logic to invoke callback function once all the ajax calls are completed, in success handler.
    succ = ajaxObjs[i]['success'];
    ajaxObjs[i]['success'] = function(data) { //modified success handler
      if (succ) {
        succ(data);
      }
      ajaxCount--;
      if (ajaxCount == 0) {
        fn(); //modify statement suitably if you want 'this' keyword to refer to another object
      }
    };
    $.ajax(ajaxObjs[i]); //make ajax call
    succ = null;
  };

예 : doSomething함수는를 사용합니다 untilAjax.

function doSomething() {
  // variable declarations
  untilAjax([{
    url: 'url2',
    dataType: 'json',
    success: function(data) {
      //do something with success data
    }
  }, {
    url: 'url1',
    dataType: 'json',
    success: function(data) {
      //do something with success data
    }
  }, {
    url: 'url2',
    dataType: 'json',
    success: function(response) {
      //do something with success data
    }
  }], function() {
    // logic after all the calls are completed.
  });
}

2

처음부터 시작하는 경우 $ .when ()을 사용하는 것이 좋습니다 .

이 질문에 백만 개가 넘는 답변이 있지만 여전히 내 사건에 유용한 것을 찾지 못했습니다. 기존 코드베이스를 처리하고 이미 일부 아약스 호출을 수행해야하며 약속의 복잡성을 도입하거나 전체를 다시 실행하고 싶지 않다고 가정 해 봅시다.

우리는 쉽게 jQuery를 활용할 수 있습니다 .data, .on그리고.trigger 영원히 이후 jQuery를의 한 부분이었다 기능.

코드 펜

내 솔루션에 대한 좋은 점은 다음과 같습니다.

  • 콜백이 정확히 무엇에 의존하는지는 분명합니다.

  • 이 함수 triggerNowOrOnLoaded는 데이터가 이미로드되었는지 또는 우리가 여전히 기다리고 있는지 상관하지 않습니다.

  • 기존 코드에 연결하는 것이 매우 쉽습니다.

$(function() {

  // wait for posts to be loaded
  triggerNowOrOnLoaded("posts", function() {
    var $body = $("body");
    var posts = $body.data("posts");

    $body.append("<div>Posts: " + posts.length + "</div>");
  });


  // some ajax requests
  $.getJSON("https://jsonplaceholder.typicode.com/posts", function(data) {
    $("body").data("posts", data).trigger("posts");
  });

  // doesn't matter if the `triggerNowOrOnLoaded` is called after or before the actual requests 
  $.getJSON("https://jsonplaceholder.typicode.com/users", function(data) {
    $("body").data("users", data).trigger("users");
  });


  // wait for both types
  triggerNowOrOnLoaded(["posts", "users"], function() {
    var $body = $("body");
    var posts = $body.data("posts");
    var users = $body.data("users");

    $body.append("<div>Posts: " + posts.length + " and Users: " + users.length + "</div>");
  });

  // works even if everything has already loaded!
  setTimeout(function() {

    // triggers immediately since users have been already loaded
    triggerNowOrOnLoaded("users", function() {
      var $body = $("body");
      var users = $body.data("users");

      $body.append("<div>Delayed Users: " + users.length + "</div>");
    });

  }, 2000); // 2 seconds

});

// helper function
function triggerNowOrOnLoaded(types, callback) {
  types = $.isArray(types) ? types : [types];

  var $body = $("body");

  var waitForTypes = [];
  $.each(types, function(i, type) {

    if (typeof $body.data(type) === 'undefined') {
      waitForTypes.push(type);
    }
  });

  var isDataReady = waitForTypes.length === 0;
  if (isDataReady) {
    callback();
    return;
  }

  // wait for the last type and run this function again for the rest of the types
  var waitFor = waitForTypes.pop();
  $body.on(waitFor, function() {
    // remove event handler - we only want the stuff triggered once
    $body.off(waitFor);

    triggerNowOrOnLoaded(waitForTypes, callback);
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>Hi!</body>


2

모든 아약스로드가 완료되면 크기 확인을 사용하고 있습니다.

function get_ajax(link, data, callback) {
    $.ajax({
        url: link,
        type: "GET",
        data: data,
        dataType: "json",
        success: function (data, status, jqXHR) {
            callback(jqXHR.status, data)
        },
        error: function (jqXHR, status, err) {
            callback(jqXHR.status, jqXHR);
        },
        complete: function (jqXHR, status) {
        }
    })
}

function run_list_ajax(callback){
    var size=0;
    var max= 10;
    for (let index = 0; index < max; index++) {
        var link = 'http://api.jquery.com/ajaxStop/';
        var data={i:index}
        get_ajax(link,data,function(status, data){
            console.log(index)
            if(size>max-2){
                callback('done')
            }
            size++
            
        })
    }
}

run_list_ajax(function(info){
    console.log(info)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>


예를 들어
MarwaAhmad

2

Alex의 답변을 확장하기 위해 가변 인수와 약속이있는 예가 있습니다. 나는 ajax를 통해 이미지를로드하고 이미지가 모두로드 된 후 페이지에 표시하고 싶었다.

이를 위해 다음을 사용했습니다.

let urlCreator = window.URL || window.webkitURL;

// Helper function for making ajax requests
let fetch = function(url) {
    return $.ajax({
        type: "get",
        xhrFields: {
            responseType: "blob"
        },
        url: url,
    });
};

// Map the array of urls to an array of ajax requests
let urls = ["https://placekitten.com/200/250", "https://placekitten.com/300/250"];
let files = urls.map(url => fetch(url));

// Use the spread operator to wait for all requests
$.when(...files).then(function() {
    // If we have multiple urls, then loop through
    if(urls.length > 1) {
        // Create image urls and tags for each result
        Array.from(arguments).forEach(data => {
            let imageUrl = urlCreator.createObjectURL(data[0]);
            let img = `<img src=${imageUrl}>`;
            $("#image_container").append(img);
        });
    }
    else {
        // Create image source and tag for result
        let imageUrl = urlCreator.createObjectURL(arguments[0]);
        let img = `<img src=${imageUrl}>`;
        $("#image_container").append(img);
    }
});

단일 또는 여러 URL에 대해 작동하도록 업데이트되었습니다 : https://jsfiddle.net/euypj5w9/


2

다른 답변에서 언급했듯이 ajaxStop()모든 아약스 요청이 완료 될 때까지 기다릴 수 있습니다 .

$(document).ajaxStop(function() {
     // This function will be triggered every time any ajax request is requested and completed
});

특정 ajax()요청에 대해 원하는 경우 complete()특정 ajax 요청 내부에서 메소드를 사용하는 것이 가장 좋습니다 .

$.ajax({
    type: "POST",
    url: "someUrl",
    success: function(data) {
        // This function will be triggered when ajax returns a 200 status code (success)
    },
    complete: function() {
        // This function will be triggered always, when ajax request is completed, even it fails/returns other status code
    },
    error: function() {
        // This will be triggered when ajax request fail.
    }
});


그러나 몇 가지 특정 아약스 요청이 완료 될 때까지 기다려야합니까? 기다릴 멋진 아약스가 끝날 때까지 기다릴 멋진 자바 스크립트 약속 을 사용하십시오 . 약속이 ajax와 어떻게 작동하는지 보여주기 위해 짧고 쉽고 읽기 쉬운 예제를 만들었습니다.
다음 예를 살펴보십시오 . 내가 사용 setTimeout예제를 명확히 할 수 있습니다.

// Note:
// resolve() is used to mark the promise as resolved
// reject() is used to mark the promise as rejected

$(document).ready(function() {
    $("button").on("click", function() {

        var ajax1 = new Promise((resolve, reject) => {
            $.ajax({
                type: "GET",
                url: "https://miro.medium.com/max/1200/0*UEtwA2ask7vQYW06.png",
                xhrFields: { responseType: 'blob'},
                success: function(data) {
                    setTimeout(function() {
                        $('#image1').attr("src", window.URL.createObjectURL(data));
                        resolve(" Promise ajax1 resolved");
                    }, 1000);
                },
                error: function() {
                    reject(" Promise ajax1 rejected");
                },
            });
        });

        var ajax2 = new Promise((resolve, reject) => {
            $.ajax({
                type: "GET",
                url: "https://cdn1.iconfinder.com/data/icons/social-media-vol-1-1/24/_github-512.png",
                xhrFields: { responseType: 'blob' },
                success: function(data) {
                    setTimeout(function() {
                         $('#image2').attr("src", window.URL.createObjectURL(data));
                         resolve(" Promise ajax2 resolved");
                    }, 1500);
                },
                error: function() {
                    reject(" Promise ajax2 rejected");
                },
            });
        });

        var ajax3 = new Promise((resolve, reject) => {
            $.ajax({
                type: "GET",
                url: "https://miro.medium.com/max/632/1*LUfpOf7teWvPdIPTBmYciA.png",
                xhrFields: { responseType: 'blob' },
                success: function(data) {
                    setTimeout(function() {
                         $('#image3').attr("src", window.URL.createObjectURL(data));
                         resolve(" Promise ajax3 resolved");
                    }, 2000);
                },
                error: function() {
                    reject(" Promise ajax3 rejected");
                },
            });
        });
        
        Promise.all([ajax1, ajax2, ajax3]).then(values => {
            console.log("We waited until ajax ended: " + values);
            console.log("My few ajax ended, lets do some things!!")
        }, reason => {
            console.log("Promises failed: " + reason);
        });
        
        // Or if you want wait for them individually do it like this
        // ajax1.then(values => {
        //    console.log("Promise 1 resolved: " + values)
        // }, reason => {
        //     console.log("Promise 1 failed: " + reason)
        // });
    });

});
img {
  max-width: 200px;
  max-height: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Make AJAX request</button>
<div id="newContent">
    <img id="image1" src="">
    <img id="image2" src="">
    <img id="image3" src="">
</div>


0

나는 간단한 방법을 찾았다. shift()

function waitReq(id)
{
  jQuery.ajax(
  {
    type: 'POST',
    url: ajaxurl,
    data:
    {
      "page": id
    },
    success: function(resp)
    {
      ...........
      // check array length if not "0" continue to use next array value
      if(ids.length)
      {
        waitReq(ids.shift()); // 2
      )
    },
    error: function(resp)
    {
      ....................
      if(ids.length)
      {
        waitReq(ids.shift());
      )
    }
  });
}

var ids = [1, 2, 3, 4, 5];    
// shift() = delete first array value (then print)
waitReq(ids.shift()); // print 1

0

내 해결책은 다음과 같습니다

var request;
...
'services': {
  'GetAddressBookData': function() {
    //This is the primary service that loads all addressbook records 
    request = $.ajax({
      type: "POST",
      url: "Default.aspx/GetAddressBook",
      contentType: "application/json;",
      dataType: "json"
    });
  },

  ...

  'apps': {
    'AddressBook': {
      'data': "",
      'Start': function() {
          ...services.GetAddressBookData();
          request.done(function(response) {
            trace("ajax successful");
            ..apps.AddressBook.data = response['d'];
            ...apps.AddressBook.Filter();
          });
          request.fail(function(xhr, textStatus, errorThrown) {
            trace("ajax failed - " + errorThrown);
          });

꽤 잘 작동했습니다. 나는 이것을하는 많은 다른 방법을 시도했지만 이것이 가장 단순하고 재사용 가능한 것으로 나타났습니다. 그것이 도움이되기를 바랍니다.


0

내 해결책을보십시오 :

1.이 함수 (및 변수)를 자바 스크립트 파일에 삽입하십시오.

var runFunctionQueue_callback;

function runFunctionQueue(f, index, callback) {

  var next_index = index + 1

  if (callback !== undefined) runFunctionQueue_callback = callback;

  if (f[next_index] !== undefined) {
    console.log(index + ' Next function avalaible -> ' + next_index);
    $.ajax({
      type: 'GET',
      url: f[index].file,
      data: (f[index].data),
      complete: function() {
        runFunctionQueue(f, next_index);
      }
    });
  } else {
    console.log(index + ' Last function');
    $.ajax({
      type: 'GET',
      url: f[index].file,
      data: (f[index].data),
      async: false,
      complete: runFunctionQueue_callback
    });
  }
}

다음과 같이 요청으로 배열을 작성하십시오.

var f = [
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}},
           {file: 'file_path', data: {action: 'action', data: 'any_data}}
        ];

3. 콜백 함수 생성 :

function Function_callback() {
  alert('done');
}

4. runFunctionQueue 함수를 매개 변수로 호출하십시오.

runFunctionQueue(f, 0, QuestionInsert_callback);
// first parameter: array with requests data
// second parameter: start from first request
// third parameter: the callback function


-4

이 방법으로 시도하십시오. 자바 스크립트 함수 내에서 루프를 만들어 아약스 호출이 끝날 때까지 기다리십시오.

function getLabelById(id)
{
    var label = '';
    var done = false;
    $.ajax({
       cache: false,
       url: "YourMvcActionUrl",
       type: "GET",
       dataType: "json",
       async: false,
       error: function (result) {
         label='undefined';
         done = true;
        },
       success: function (result) {
            label = result.Message;
            done = true;
        }
     });

   //A loop to check done if ajax call is done.
   while (!done)
   {
      setTimeout(function(){ },500); // take a sleep.
   }

    return label;
}

1
당신 setTimeout()은하지 않습니다 take a sleep. 이 경우 donetrue가 될 때까지 모든 탭을 차단하면 됩니다.
Alexis Wilke

1
"jQuery Ajax 요청이 모두 완료 될 때까지 기다리십시오"라고 묻는 주제입니다.
ChinaHelloWorld

1
이 코드를 테스트 했습니까? 내 기대는 donewhile 루프가 여전히 실행되는 동안 결코 사실이 아닐 것입니다. while 루프가 실행 중이면 이벤트 루프를 계속할 수 없으므로 ajax 성공에 대한 콜백을 실행하지 않습니다.
Kevin B
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.