Зачекайте, поки всі запити jQuery Ajax будуть виконані?


675

Як змусити функцію чекати, поки всі запити jQuery Ajax будуть виконані всередині іншої функції?

Коротше кажучи, мені потрібно дочекатися, коли всі запити Ajax будуть виконані, перш ніж виконати наступний. Але як?


Як ви називаєте свої оригінальні запити на ajax?
NakedBrunch

2
Що ви маєте на увазі під "зробленим"? Я розумію це як "всі запити закінчені або успішно, або ні" (вирішено або відхилено). Але ви можете мати на увазі "всі запити успішно закінчені" (вирішено). дивіться всі варіанти в api.jquery.com/category/deferred-object
Adrien Be

Відповіді:


911

jQuery тепер визначає функцію if для цієї мети.

Він приймає в якості аргументів будь-яку кількість відкладених об'єктів і виконує функцію, коли всі вони вирішуються.

Це означає, що якщо ви хочете ініціювати (наприклад) чотири запити 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, які могли б мати небажані побічні ефекти в міру розвитку вашої сторінки.

Якщо ви не знаєте заздалегідь, скільки аргументів ajax потрібно чекати (тобто ви хочете використовувати змінну кількість аргументів), це все одно можна зробити, але це лише трохи складніше. Див. Перехід у масиві відкладених до $ .when () (і, можливо, jQuery .при усуненні несправностей зі змінною кількістю аргументів ).

Якщо вам потрібен більш глибокий контроль над режимами відмов сценаріїв ajax тощо, ви можете зберегти повернутий об'єкт .when()- це об’єкт jQuery Promise, що охоплює всі оригінальні запити ajax. Ви можете зателефонувати .then()або .fail()на нього, щоб додати детальний обробник успіху / відмови.


46
Це слід позначити як правильну відповідь, оскільки це просто, ефективно та чудово працює. Також слід зазначити, що $.whenповертає Promiseоб'єкт, який має не тільки корисні методи .done. Наприклад, за допомогою .then(onSuccess, onFailure)методу ви могли б відреагувати, коли обидва запити вдаються або принаймні один з них не вдається.
skalee

2
Чи можна зв'язати запити ajax1..4 в масив і передати це?
andig

33
Будьте обережні зі failсправою. На відміну від цього done, failпожежі одразу на перших збоях і ігнорування решти відкладених.
Ryan Mohr

1
@skalee дякую за те, що підкреслив той факт, що onFailureфункцію можна було приєднати. Як я зазначив у коментарі до питання ОП: він, можливо, захоче точніше вказати, що він мав на увазі під «зробив». «Райан Мор» було також дуже хороший момент про те , що failповодиться по- іншому , як done, деякі подальше читання , щоб бути зроблено , Promisesя думаю , html5rocks.com/en/tutorials/es6/promises
Adrien Be

1
Чудово піддавати людям вплив на метод коли та на обіцянки взагалі, але я думаю, що це не найкраща відповідь. Якщо будь-яка з цих функцій ajax в будь-якій точці лінії створює ще один запит ajax, а потім не інтегруйте цю нову обіцянку в ланцюг правильно ... ці запити не зможуть уникнути цієї методики. Наприклад, я не можу використовувати цю техніку, не змінюючи бібліотеку Shopify, яку я використовую для поведінки додатків до кошика ajax, тому що вона не була написана «перспективно» і ніколи не повертає створені ними об’єкти xhr. Це має сенс? Ще чудова відповідь, хоча!
Ziggy

292

Якщо ви хочете дізнатися, коли всі ajax запити закінчуються у вашому документі, незалежно від того, скільки їх існує, просто використовуйте $ .ajaxStop подія таким чином:

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

У цьому випадку ні вам не потрібно здогадуватися, скільки запитів відбувається в додатку, які можуть закінчитися в майбутньому, і не занурюватися у функції складної логіки або знаходити, які функції виконують HTTP(S)запити.

$.ajaxStopтут також можна прив’язати будь-який HTMLвузол, який, на вашу думку, може бути змінений реквестом.


Оновлення:
якщо ви хочете дотримуватися 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 / wait :

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

16
+1 Набагато краще, ніж інші відповіді, якщо вам доведеться мати справу зі сторонніми сценаріями з анонімними зворотами / закриттями дзвінків.
кайзер

5
@kaiser Дійсна точка, але це не те, про що ставили питання. Це не дуже добре, якщо ви не хочете чекати повернення всіх дзвінків AJAX. Питання є специфічним щодо очікування викликів AJAX, які ви здійснили самостійно (називаються всередині іншої функції, як писав ОП). Можливо, якийсь інший код здійснив черговий дзвінок AJAX, якого ви не хочете чекати.
Хуан Мендес

6
У порівнянні з рішенням коли (), воно має перевагу працювати, навіть якщо кількість викликів ajax не відома.
Олексій Дуфреной

5
У порівнянні з рішенням коли (), у нього є великий недолік - не працювати добре разом з іншими компонентами, оскільки він поділяє загальнодокументальний глобальний стан. Якщо постійно триватиме тривале опитування, воно може навіть не припинятися.
Бергі

3
Ви неправі @AdrienBe, ajaxStop обробляє всі запити ajax незалежно від того, чи вдаються вони чи ні, так само як доказ моїх слів дивіться на цей jsfiddle.net/36votxba/2
Арсен Хачатурян

32

Я знайшов хорошу відповідь від gnarf my self, який саме те, що я шукав :)

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 запитів ajax, і ви хочете приховати це повідомлення після завантаження.

Від документа jQuery :

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

Зверніть увагу, що він буде чекати, коли всі запити Ajax будуть виконані на цій сторінці.


5
Це передбачає, що ви знаєте, що на сторінці не буде жодних інших запитів AJAX, не дуже хороше припущення
Хуан Мендес

Станом на jQuery 1.8, .ajaxStop () метод повинен бути доданий лише до документа.
Геоморілло

1
Виправте мене, якщо я помиляюся, але чи не перетворить це ваш проект на веб-сайт "старі шкільні форми"? Я маю на увазі, якщо ви маєте всю вашу сторінку дочекатися запиту, перш ніж він може продовжуватися, то в чому сенс запиту ajax в першу чергу?
BillRuhl

@BillRuhl в нашому випадку я перебираю колекцію jquery, щоб створити нові речі і потрібно знати про всю колекцію, коли це буде зроблено, перш ніж вносити деякі коригування макета. Це не здається особливо незвичним випадком. Було б погано, якби купу інших аяксів може бути в процесі роботи, але тут цього не буде.
еон

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
Це насправді не все так складно. Підрахунок семафорів є загальним механізмом роботи в КС. Якщо ви віддаєте перевагу, приклад, який використовує черги jQuery, також спрацював, не потребуючи самостійного впровадження семафору.
BBonifield

1
Я не бачу проблеми з лічильником семафору, однак я бачу проблему з ідеєю мати ЧЕТВЕРНІ функції для обробки результату зворотного виклику. Спершу слід визначити функцію, а потім посилатися на цю функцію в кожній .get(). Таким чином ви принаймні не дублюєте цей код. Мало того, але декларування function(){}кожного разу виділяє пам'ять кожного разу! Досить погана практика, якщо ви можете викликати статично визначену функцію.
Алексіс Вілке

1
@AlexisWilke Це відповідь 4,5 років, і вона мала бути прикладом того, як працюють семафори та черги. Ви занадто важко думаєте з цього приводу, і я не думаю, що КАПІТАЛІЗАЦІЯ ДЛЯ ЗАЯВЛЕННЯ ОК
BBonifield

2
Ну ... я не той, хто дав вам -1 ... і я розумію, що відповіді, як правило, старіють. Тим не менш, люди продовжують їх знаходити, і наскільки я знаю, не забороняється давати інформацію людям, які потенційно ними можуть скористатися і сьогодні.
Алексіс Вілке

8

javascript заснований на подіях, тому вам ніколи не варто чекати , а встановлюйте гачки / зворотні дзвінки

Ви, ймовірно, можете просто скористатися методами успіху / завершення 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...
  }
});

хоча ви повинні опублікувати псевдокод того, як ваші (-і) запити (-и) ajax (-и) називаються більш точними ...


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
Особливо, якщо запит провалюється або триває довгий час з якоїсь непередбачуваної причини (що, згідно із Законом Мерфі, неодмінно трапиться!), Це зазвичай погана ідея для виробничого коду через блокування браузера, як зазначено вище.
Олексій

27
Це жахливо погана ідея. НЕ ВИКОРИСТОВУЙТЕ ЦЕ ВІДПОВІДЬ.
Таурен

2

Якщо вам потрібно щось просте; один раз і готовий зворотний дзвінок

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

4
це може генерувати нескінченний цикл!
Дієго Фаверо

2
Це нескінченна петля? Коли? Коли AJAX ніколи не повертається?
Джонатан

2

Також ви можете використовувати async.js .

Я думаю, що це краще, ніж $ .when тому, що ви можете об'єднати всі види асинхронного дзвінка, який не підтримує обіцянки поза коробкою, як тайм-аути, дзвінки SqlLite тощо, а не лише запити ajax.


2

На основі відповіді @BBonifield я написав функцію утиліти, щоб логіка семафору не поширювалася на всі виклики ajax.

untilAjax це утиліта, яка викликає функцію зворотного виклику, коли всі ajaxCalls виконані.

ajaxObjs це масив об'єктів налаштування ajax [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 (), якщо ви починаєте з нуля.

Незважаючи на те, що це питання має понад мільйон відповідей, я все одно не знайшов нічого корисного для моєї справи. Скажімо, вам доведеться мати справу з існуючою базою кодів, вже здійснюючи деякі дзвінки ajax і не хочуть вводити складність обіцянок та / або повторювати все.

Ми легко можемо скористатися JQuery .data, .onі .triggerфункції , які були частиною JQuery з тих пір назавжди.

Codepen

Хороший матеріал про моє рішення:

  • очевидно, від чого саме залежить зворотний дзвінок

  • функцію 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

Я використовую перевірку розміру, коли завершено все завантаження ajax

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

Щоб розширити відповідь Алекса, я маю приклад зі змінними аргументами та обіцянками. Я хотів завантажити зображення через 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()зачекати, поки всі запити на Ajax будуть виконані.

$(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? Використовуйте чудові javascript- обіцянки почекати, поки ці аякси, яких ви хочете чекати, будуть виконані. Я зробив короткий, простий і зрозумілий приклад, щоб показати вам, як обіцянки працюють з 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. Вставте цю функцію (та змінну) у свій файл JavaScript:

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

2.Будуйте масив зі своїми запитами, наприклад:

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

Спробуйте таким чином. зробіть цикл всередині функції сценарію java, щоб зачекати, поки виклик Ajax завершиться.

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. У цьому випадку ви просто блокуєте всі вкладки, поки не doneстане істинним.
Алексіс Вілке

1
Я думаю, що ця тема просить: "Зачекайте, поки всі запити jQuery Ajax будуть виконані".
ChinaHelloWorld

1
Ви протестували цей код? моє сподівання - це doneніколи не буде правдою, поки цикл поки працює. Якщо цикл пока працює, цикл подій не може продовжуватися і тому ніколи не запускатиме зворотний виклик до успіху ajax.
Кевін Б
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.