Jeśli chcę mieć funkcje synchroniczne i asynchroniczne wykonywać w określonej kolejności, mógłbym użyć jQuery obietnicy, ale wydaje się, że nie działa tak, jak spodziewałbym się pracować.

Funkcje A, B i C powinny wykonać w tej kolejności, gdy nazywa się w deferred.resolve(), spodziewam się, że funkcja B ma zostać wykonana, ale wszystkie funkcje są wykonywane natychmiast bez względu na to, że zostanie wywołana rozwiązanie.

Oto kod:

function a(){
  var deferred = $.Deferred();
  setTimeout(function(){
    console.log("status in a:",deferred.state());
    //this should trigger calling a or not?
    deferred.resolve("from a");
  },200);
  console.log("a");
  return deferred.promise();
};
function b(){
  var deferred = $.Deferred();
  setTimeout(function(){
    console.log("status in b:",deferred.state());
    deferred.resolve("from b");
  },200);
  console.log("b");
  return deferred.promise();
}
//synchronous function
function c(){
  var deferred = $.Deferred();
  console.log("c");
  console.log("status in c:",deferred.state());
  deferred.resolve("from c");
  return deferred.promise();
}
function test(){
  fn=[a,b,c],i=-1,
  len = fn.length,d,
  d = jQuery.Deferred(),
  p=d.promise();
  while(++i<len){
    p=p.then(fn[i]);
  }
  p.then(function(){
    console.log("done");
  },
  function(){
    console.log("Failed");
  });
  d.resolve();
  //instead of the loop doing the following has the same output
  //p.then(a).then(b).then(c);
  //d.resolve();
}
test();

Wynik to:

a
b
status in c: pending
c
done
status in a: pending
status in b: pending

Oczekiwany wynik:

a
status in a: pending
b
status in b: pending
c
status in c: pending
done

Próbowałem niektórych kombinacji następujących modyfikacji:

  d = jQuery.Deferred();
  setTimeout(function(){d.resolve();},100);
  var p=d.promise();
  while(++i<len){
    p.then(fn[i]);
  }

Ale wszystkie z tych samych nieoczekiwanych wyników, B zostaną wywołane przed odroczeniem a został rozwiązany, C zostanie wywołany przed odroczeniem B, zostanie rozwiązany.

13
HMR 21 listopad 2013, 17:25

3 odpowiedzi

Najlepsza odpowiedź

W przypadku jQuery przed 1.8 jest to problem, ale dla nowych wersji jQuery nie jest już problemem:

function test(){
  var d = jQuery.Deferred(), 
  p=d.promise();
  //You can chain jQuery promises using .then
  p.then(a).then(b).then(c);
  d.resolve();
}
test();

PRÓBNY

Poniżej znajduje się demo jQuery 1.7.2

PRÓBNY

9
Khanh TO 21 listopad 2013, 14:25

JQuery & lt; 1.8 jest delikatnym łańcuchem Wrt, wystarczy użyć .pipe zamiast .then. 1.8 Wystarczy zmienić .then, aby być .pipe.

2
Esailija 21 listopad 2013, 16:48

Sidenote: Kiedy używasz go bez tablicy, nie musisz zaczynać od obietnicy. $.when({}).then(a).then(b) zrobi sztuczkę w porządku. Musisz tylko upewnić się, że nie umieścisz a wewnątrz when.

1
Bet Lamed 28 maj 2014, 01:30