2015-03-06 29 views
32

Jak rozumiem, obietnica jest czymś, co może rozwiązać() lub odrzucić(), ale byłem zaskoczony, aby dowiedzieć się, że kod w obietnicy jest nadal wykonywany po wywołaniu rozstrzygnięcia lub odrzucenia.Dlaczego program javascript ES6 obiecuje kontynuować wykonywanie po rozwiązaniu?

Rozważałem rozwiązanie lub odrzucenie jako przyjazną asynchroniczną wersję wyjścia lub powrotu, która zatrzymałaby natychmiastowe wykonywanie wszystkich funkcji.

Może ktoś wyjaśnić, dlaczego za Poniższy przykład pokazuje console.log czasami po wywołaniu rozwiązać myśl:

var call = function() { 
    return new Promise(function(resolve, reject) { 
     resolve(); 
     console.log("Doing more stuff, should not be visible after a resolve!"); 
    }); 
}; 

call().then(function() { 
    console.log("resolved"); 
}); 

jsbin

+5

uzasadnione pytanie, ale potem znowu, JS tylko jedno oświadczenie wykonuje po kolei jak powiesz do niego do. 'resolve()' nie jest instrukcją sterującą JS, która w magiczny sposób miałaby efekt 'return', jest po prostu wywołaniem funkcji i tak, wykonanie jest kontynuowane po tym. –

+0

To jest dobre pytanie i nawet po przeczytaniu wszystkich odpowiedzi nie jestem pewien co do najlepszych praktyk ... –

Odpowiedz

61

JavaScript ma koncepcję "run to completion". Jeśli nie zostanie zgłoszony błąd, funkcja jest wykonywana do momentu osiągnięcia instrukcji return lub jej końca. Inny kod spoza funkcji nie może temu zaradzić (chyba, że ​​ponownie zostanie zgłoszony błąd).

Jeśli chcesz resolve() aby zakończyć swoją funkcję initialiser, trzeba poprzedzić go return:

return new Promise(function(resolve, reject) { 
    return resolve(); 
    console.log("Not doing more stuff after a return statement"); 
}); 
+0

Cześć Felix - Myślę, że to tylko część historii - druga część jest taka, że ​​'resolve()' samo w sobie jest funkcją asynchroniczną. Jak widzieliśmy w drugiej (usuniętej) odpowiedzi, niektórzy ludzie uważają, że wywołanie 'resolve' spowoduje natychmiastowe wywołanie callbacków. – Alnitak

+2

Samo 'resolve''Alnitak nie jest asynchroniczne, jest całkowicie synchroniczne. Mimo że używa się wyłącznie interfejsu API ES6, nie można zaobserwować, czy jest on synchroniczny czy asynchroniczny. – Esailija

+0

@Eailailija ok, być może byłem niejasny. Niektórzy uważają, że wywołanie 'resolve' spowoduje natychmiastowe wywołanie zarejestrowanych wywołań zwrotnych, które będą częścią bieżącego stosu wywołań. To nieprawda, zamiast tego po prostu kolejkuje wywołania zwrotne (i masz rację, nie jest to asynchroniczne, ale po prostu działa i natychmiast się kończy) – Alnitak

14

wywołania zwrotne, które będą wywoływane podczas resolve obietnica nadal wymagane przez specyfikację, aby można je było nazwać asynchronicznie. Ma to zapewnić spójne zachowanie przy korzystaniu z obietnic dla kombinacji działań synchronicznych i asynchronicznych.

Dlatego kiedy powoływać resolve wywołanie zwrotne jest kolejce i kontynuuje wykonywanie funkcji bezpośrednio z dowolnym kodem poniższego zaproszenia resolve().

Tylko wtedy, gdy pętla zdarzeń JS zostanie przekazana z powrotem, wywołanie zwrotne może zostać usunięte z kolejki i faktycznie wywołane.

+0

Kolejkowanie wywołań zwrotnych jest udokumentowane w specyfikacjach A + lub w ES6? – thefourtheye

+4

@thefourtheye: Specyfikacja pętli zdarzeń jest obecnie częścią [HTML5] (http://www.w3.org/TR/html5/webappapis.html#event-loops). ES6 definiuje wewnętrzną metodę o nazwie [** 'EnqueueJob' **] (https://people.mozilla.org/~jorendorff/es6-draft.html#sec-enqueuejob), która jest wywoływana przez [**. '**] (https://people.mozilla.org/~jorendorff/es6-draft.html#sec-promise.prototype.then). –

+0

@FelixKling Oh thanks :) – thefourtheye

Powiązane problemy