Zrobiłem duży refactor i tutaj jest one final working example, z monitorowaniem postępu.
Teraz ważne części.
- Opóźnienia JQuery nie wywołują żadnych wywołań zwrotnych postępu po wywołaniu rozstrzygnięcia (with one exception). W twoim przykładzie (bez setTimeout), odroczony jest natychmiast rozwiązywany, bez szans na uruchomienie postępu.
- Wykonaj haczyki wszystkich wywołań zwrotnych, szczególnie tych postępowych, przed uruchamiamy obiekt na ostatecznym Odroczeniu. Osiąga się to poprzez przekazanie ostatecznego Odroczonego (obecnie sygnału nawigacyjnego) do funkcji wykonawczej, po, które wypełniliśmy wyzwalacze.
- I refactored API, aby func do wykonania jest odłożone agnostykiem.
- To rozwiązanie wykorzystuje closure funkcji lokalnej (do funkcji zmniejszania iteracji) Odroczonej, wewnątrz funkcji memo.then, w celu kontynuowania łańcucha wykonawczego.
EDYCJA: Zapomniałem pierwszego pytania. To zachowanie jest osiągane za pomocą funkcji closure (zmienna dfd w funkcji "x").
Funkcja "x" natychmiast zwraca (po wywołaniu zdarzenia powiadomienia, które można teraz przetworzyć, ponieważ wszystkie Odroczone łańcucha wykonawczego zostały utworzone, a zakończone, niepowodzenie, przechwytywania postępu "executePromiseQueueSync" zostały haczykowaty).
Funkcja "setTimeout" "zamyka" dfd w zamknięciu, dzięki czemu może uzyskać dostęp do zmiennej pomimo powrotu "x". Wywołanie "wtedy" jest kontynuowane poprzez utworzenie następnego odroczonego, powiązanego z pierwszym.
Po uzyskaniu VM VM (nie ma innych rzeczy do zrobienia), setTimeout wyzwala jego powiązaną funkcję, która (przez zamknięcie) ma dostęp do "zamkniętej" zmiennej dfd. Odroczony jest rozwiązywany i łańcuch może być kontynuowany.
EDIT2:
Here is a refactored version, która dodaje obsługę długich uruchomień, odroczonych obsługiwanych funkcji, w których powiadamia dzwoniącego o swoich postępach.
EDIT3: Tutaj jest another version, bez podkreślenia wiązania i z przykładem jq-ui progressbar.
Przy okazji jest to bardzo dobry pomysł na skomplikowane procedury inicjowania aplikacji.
Źródło (w pierwszej wersji)
function executePromiseQueueSync(queue, beacon){
var seed = $.Deferred(),
le = queue.length,
last;
beacon.notify(0);
last = _.reduce(queue, function(memo, ent, ind){
var df = $.Deferred();
df.then(function(){
console.log("DBG proggie");
beacon.notify((ind+1)/le*100);
});
console.log("DBG hook funk "+ind);
memo.then(function(){
console.log("DBG exec func "+ind);
ent.funct.apply(null, ent.argmnt);
df.resolve();
});
return df.promise();
}, seed.promise());
last.then(function(){
beacon.resolve(100)
});
seed.resolve(); // trigger
return beacon.promise();
}
function x(){
// do stuff
console.log("blah");
}
var promisesQueue = [],
beacon = $.Deferred();
promisesQueue.push({funct: x, argmnt:[]});
promisesQueue.push({funct: x, argmnt:[]});
promisesQueue.push({funct: x, argmnt:[]});
function monTheProg(pct)
{
console.log('progress '+pct);
}
// first hook, then exec
beacon.then(function(){
console.log('success');
}, function(){
console.log('failure');
}, monTheProg);
// do the dance
executePromiseQueueSync(promisesQueue, beacon)
Wystarczy dodać kilka podstawowych informacji z ostatniego pytania Powodem setTimeout jest wymagane został rozwiązany odroczone obiekty nie mogą mieć więcej wydarzeń postępu prac związanych z nimi. Opóźniając rozstrzygnięcie, ".then" jest w stanie powiązać ze zdarzeniem progress. –
To dość buńczuczne zachowanie, jeśli zdasz sobie sprawę z wszystkich subtelnych konsekwencji. – mnowotka
Jest jedna część tego, czego nie całkiem rozumiem. W jaki sposób .then wychwycić .notify, który jest wywoływany przed powrotem tego wywołania zwrotnego, gdy opóźniamy rozstrzygnięcie? Pomyśl o tym. . then pobiera obiekt odroczony, który został zwrócony z jego pierwszego parametru i tworzy z niego nowy obiekt odroczony, wiążąc się z wykonanymi postępami i zdarzeniami fail. Jeśli powiadomienie zostało wywołane przed odesłaniem odroczonym, jak jest możliwe, aby wyłapać to nawet przy użyciu setTimeout? –