Co robi $.kiedy.apply ($, someArray) do?

Czytam o Odroczeniach i obietnicach i ciągle natykam się $.when.apply($, someArray). Jestem trochę niejasny, co to dokładnie robi, Szukam wyjaśnienia, że jedna linia działa dokładnie (Nie cały fragment kodu). Oto jakiś kontekst:

var data = [1,2,3,4]; // the ids coming back from serviceA
var processItemsDeferred = [];

for(var i = 0; i < data.length; i++){
  processItemsDeferred.push(processItem(data[i]));
}

$.when.apply($, processItemsDeferred).then(everythingDone); 

function processItem(data) {
  var dfd = $.Deferred();
  console.log('called processItem');

  //in the real world, this would probably make an AJAX call.
  setTimeout(function() { dfd.resolve() }, 2000);    

  return dfd.promise();
}

function everythingDone(){
  console.log('processed all items');
}
Author: Stobbej, 2013-02-08

6 answers

.apply jest używany do wywołania funkcji z tablicą argumentów. Przyjmuje każdy element w tablicy i używa każdego jako parametru do funkcji. .apply może również zmienić kontekst (this) wewnątrz funkcji.

Więc weźmy $.when. Mówi się: "kiedy wszystkie te obietnice zostaną rozwiązane... zrób coś". Przyjmuje nieskończoną (zmienną) liczbę parametrów.

W Twoim przypadku, masz szereg obietnic; nie wiesz, ile parametrów mijasz do $.when. Przekazanie tablicy do $.when nie zadziałałoby, ponieważ oczekuje, że jej parametry będą obietnicami, a nie tablicą.

Tu wkracza .apply. Pobiera tablicę i wywołuje $.when z każdym elementem jako parametrem (i upewnia się, że {[2] } jest ustawiona na jQuery/$), więc to wszystko działa: -)

 144
Author: Rocket Hazmat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-08 16:34:26

$.gdy pobiera dowolną liczbę parametrów i rozwiązuje Gdy wszystkie z nich zostały rozwiązane.

anyFunction .apply (thisValue, arrayParameters) wywołuje funkcję anyFunction ustawiając jej kontekst (thisValue będzie this wewnątrz tego wywołania funkcji) i przekazuje wszystkie obiekty w arrayParameters jako indywidualne parametry.

Na przykład:

$.when.apply($, [def1, def2])

Jest tym samym co:

$.when(def1, def2)

Ale sposób wywołania apply pozwala aby przekazać tablicę nieznanej liczby parametrów. (W Twoim kodzie mówisz, że Dane pochodzą z usługi, wtedy jest to jedyny sposób na wywołanie $.kiedy )

 60
Author: Pablo González Alba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-08 05:36:22

Tutaj kod jest w pełni udokumentowany.

// 1. Declare an array of 4 elements
var data = [1,2,3,4]; // the ids coming back from serviceA
// 2. Declare an array of Deferred objects
var processItemsDeferred = [];

// 3. For each element of data, create a Deferred push push it to the array
for(var i = 0; i < data.length; i++){
  processItemsDeferred.push(processItem(data[i]));
}

// 4. WHEN ALL Deferred objects in the array are resolved THEN call the function
//    Note : same as $.when(processItemsDeferred[0], processItemsDeferred[1], ...).then(everythingDone);
$.when.apply($, processItemsDeferred).then(everythingDone); 

// 3.1. Function called by the loop to create a Deferred object (data is numeric)
function processItem(data) {
  // 3.1.1. Create the Deferred object and output some debug
  var dfd = $.Deferred();
  console.log('called processItem');

  // 3.1.2. After some timeout, resolve the current Deferred
  //in the real world, this would probably make an AJAX call.
  setTimeout(function() { dfd.resolve() }, 2000);    

  // 3.1.3. Return that Deferred (to be inserted into the array)
  return dfd.promise();
}

// 4.1. Function called when all deferred are resolved
function everythingDone(){
  // 4.1.1. Do some debug trace
  console.log('processed all items');
}
 13
Author: Yanick Rochon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-08 16:36:56

Niestety nie mogę się z wami zgodzić.

$.when.apply($, processItemsDeferred).always(everythingDone);

Wywoła everythingDonejak tylko jeden odroczony zostanie odrzucony, nawet jeśli istnieją inne odroczenia, które są oczekujące.

Oto pełny skrypt (polecam http://jsfiddle.net/):

var data = [1,2,3,4]; // the ids coming back from serviceA
var processItemsDeferred = [];

for(var i = 0; i < data.length; i++){
  processItemsDeferred.push(processItem(data[i]));
}

processItemsDeferred.push($.Deferred().reject());
//processItemsDeferred.push($.Deferred().resolve());

$.when.apply($, processItemsDeferred).always(everythingDone); 

function processItem(data) {
  var dfd = $.Deferred();
  console.log('called processItem');

  //in the real world, this would probably make an AJAX call.
  setTimeout(function() { dfd.resolve(); }, 2000);    

  return dfd.promise();
}

function everythingDone(){
  alert('processed all items');
}
To robal? Chciałbym użyć tego tak, jak pan powyżej to opisał.
 1
Author: user3388213,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-12 08:58:37

$.gdy sam umożliwia wywołanie zwrotne, gdy wszystkie obietnice przekazane do niego są rozwiązywane / odrzucane. Normalnie $.gdy pobiera zmienną liczbę argumentów, używając .apply pozwala przekazać mu szereg argumentów, jest bardzo potężny. Więcej informacji na .Zastosuj: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply

 0
Author: Roger C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-08 16:34:35

Dzięki za eleganckie rozwiązanie:

var promise;

for(var i = 0; i < data.length; i++){
  promise = $.when(promise, processItem(data[i]));
}

promise.then(everythingDone);

Tylko jeden punkt: gdy używasz resolveWith, aby uzyskać pewne parametry, łamie się z powodu początkowej obietnicy ustawionej na undefined. Co zrobiłem aby to działało:

// Start with an empty resolved promise - undefined does the same thing!
var promise;

for(var i = 0; i < data.length; i++){
  if(i==0) promise = processItem(data[i]);
  else promise = $.when(promise, processItem(data[i]));
}

promise.then(everythingDone);
 0
Author: user3544352,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-21 16:06:15