Ожидание на нескольких асинхронных вызовах для завершения перед продолжением

Так, у меня есть страница, которая загружается, и через jquery.get выполняет несколько запросов для заполнения холмов отбрасывания с их значениями.

$(function() {
    LoadCategories($('#Category'));
    LoadPositions($('#Position'));
    LoadDepartments($('#Department'));

    LoadContact();
};

Это затем называет LoadContact (); Который делает другой вызов, и когда он возвращается, он заполняет все поля на форме. Проблема состоит в том, что часто, раскрытие все не заполняется, и таким образом, оно не может установить их на правильное значение.

То, что я должен смочь сделать, так или иначе имеют LoadContact, только выполняются, после того как другие методы завершены и обратные вызовы, сделанные, выполняясь.

Но, я не хочу должным быть помещать набор флагов в конце выпадающих обратных вызовов населения, которые я затем проверяю и должен иметь рекурсивную проверку вызова метода setTimeout до вызова LoadContact ();

Есть ли что-то в jQuery, который позволяет мне говорить, "Выполните это, когда все они сделаны".?

Больше Информации я думаю что-то вдоль этих строк

$().executeAfter(
    function () {   // When these are done
        LoadCategories($('#Category'));
        LoadPositions($('#Position'));
        LoadDepartments($('#Department'));
    },
    LoadContact // Do this
);

... это должно было бы отслеживать вызовы ajax, которые происходят во время осуществления методов, и когда они все завершены, назовите LoadContact;

Если бы я знал, как прервать ajax, которые делаются в той функции, я мог, вероятно, записать расширение jQuery, чтобы сделать это.

Мое решение

;(function($) {
    $.fn.executeAfter = function(methods, callback) {

        var stack = [];

        var trackAjaxSend = function(event, XMLHttpRequest, ajaxOptions) {
            var url = ajaxOptions.url;

            stack.push(url);
        }

        var trackAjaxComplete = function(event, XMLHttpRequest, ajaxOptions) {
            var url = ajaxOptions.url;

            var index = jQuery.inArray(url, stack);

            if (index >= 0) {
                stack.splice(index, 1);
            }

            if (stack.length == 0) {
                callback();
                $this.unbind("ajaxComplete");
            }
        }

        var $this = $(this);

        $this.ajaxSend(trackAjaxSend)
        $this.ajaxComplete(trackAjaxComplete)

        methods();
        $this.unbind("ajaxSend");
    };
})(jQuery);

Это связывает с ajaxSend событием, в то время как методы называют, и сохраняет список URL (нуждайтесь в лучшем уникальном идентификаторе хотя), которые называют. Это затем развязывает от ajaxSend поэтому только запросы, о которых мы заботимся, прослежены. Это также связывает с ajaxComplete и удаляет объекты из стека, когда они возвращаются. Когда стек достигает нуля, он выполняет наш обратный вызов и развязывает ajaxComplete событие.

55
задан CaffGeek 4 May 2010 в 09:41
поделиться

2 ответа

Вы можете использовать .ajaxStop() вот так:

$(function() {
  $(document).ajaxStop(function() {
    $(this).unbind("ajaxStop"); //prevent running again when other calls finish
    LoadContact();
  });
  LoadCategories($('#Category'));
  LoadPositions($('#Position'));
  LoadDepartments($('#Department'));
});

Он будет запущен, когда все текущие запросы будут завершены, затем отвяжется, чтобы не запускаться, если будут выполняться последующие вызовы ajax на странице. Кроме того, убедитесь, что вы поместили его перед вызовами ajax, чтобы он был привязан достаточно рано, это более важно для .ajaxStart(), но лучше всего делать это в обоих случаях.

43
ответ дан 7 November 2019 в 07:28
поделиться

Но я не хочу помещать кучу флагов в конце выпадающих обратных вызовов населения, которые я затем проверяю, и должен иметь рекурсивную проверку вызова setTimeout перед вызовом LoadContact ();
Нет необходимости в setTimeout. Вы просто проверяете в каждом обратном вызове, что все три списка заполнены (или, лучше, настраиваете счетчик, увеличиваете его в каждом обратном вызове и ждете, пока он не станет равным 3), а затем вызываете LoadContact из обратного вызова. Мне это кажется довольно простым.

Подход ajaxStop может сработать, я просто не очень хорошо с ним знаком.

0
ответ дан 7 November 2019 в 07:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: