Как $.when, apply() и $.done() взаимодействуют в этой функции?

Некоторое время назад пользователь SO написал для меня эту функцию, чтобы возвращать переменное количество запросов jQuery $.get(). Первая часть довольно проста, но кто-нибудь объяснит, как взаимодействуют $.when(), apply() и $.done(). Я не понимаю в целом, но очень конкретно, как они получают доступ к отложенному объекту, который возвращает $.get().

function getHTML(qty_of_gets) {

   var dfdArr = [],
       i = 1;

   while (i <= qty_of_gets) {
       dfdArr.push($.get("get_test_" + i + ".php"));
       i++;
   }

   $.when.apply(null, dfdArr).done(function () {

       for (var i = 0; i < arguments.length; i++) {

           $("#content").append(arguments[i][0]);

       }

   });
}

person 1252748    schedule 04.02.2014    source источник


Ответы (3)


$.when возвращает новое обещание, поэтому $.when().done() просто вызывает .done для обещания, возвращенного $.when.

.apply вместо этого позволяет вызывать функцию с аргументами в виде массива. прохождения их по отдельности. Так

$.when.apply(null, dfdArr)

(почти*) эквивалентен

$.when(dfdArr[0], dfdArr[1], dfdArr[2], ...);

Каждый из элементов в dfdArr является обещанием.


*кроме значения this внутри функции.

person Felix Kling    schedule 04.02.2014
comment
Спасибо. Почему почти в скобках? - person 1252748; 05.02.2014
comment
Первый аргумент, передаваемый .apply, — это значение, на которое this ссылается внутри функции. $.when.apply(null, ...) означает, что this по умолчанию будет соответствовать объекту window. С $.when(...) this будет относиться к $, то есть к jQuery. Это может иметь огромное значение для функций, которые фактически используют this. - person Felix Kling; 05.02.2014

$.get() возвращает объект Deferred. В этой строке вы создаете массив, полный экземпляров Deferred, по одному для каждого вашего запроса:

dfdArr.push($.get("get_test_" + i + ".php"));

$.when() принимает список объектов Deferred и возвращает свой собственный Deferred. Когда все отложенные объекты, которые вы ему дали, разрешаются, он тоже разрешается. Обычно это что-то вроде:

$.when(dfd1, dfd2).done(function (dfd1Result, dfd2Result) {
    // The parameters from dfd1.done and dfd2.done are here in dfd1REsult, dfd2Result
}

Мы не хотим использовать список, мы хотим использовать массив. Вот тут-то и появляется .apply(). Это позволяет вам использовать массив deferred'ов.

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

person Brad    schedule 04.02.2014

Код создает массив отложенных запросов, представляющих запросы AJAX (dfdArr), и заполняет его while.

После этого apply используется для $.when, так что все эти deferred’ы передаются ему в качестве аргументов. Это приводит к возврату обещания, которое завершается, когда все первоначальные отложенные операции были успешными, т. е. когда возвращаются все запросы AJAX.

Иными словами, вызов apply является программным эквивалентом записи

$.when(dfdArr[0], ..., dfdArr[qty_of_gets - 1]).done(...);
person Jon    schedule 04.02.2014