2017-08-03 37 views
8

Mam dwie funkcje async. Obie oczekują na dwie 3-sekundowe wywołania funkcji. Ale drugi jest szybszy od pierwszego. Myślę, że szybszy biegnie równolegle, a drugi seryjnie. Czy moje założenie jest poprawne? Jeśli tak, dlaczego tak się dzieje, ponieważ obie funkcje wyglądają logicznie tak samo?Jak jest async/oczekiwać pracy w trybie szeregowym i równoległym?

function sleep() { 
    return new Promise(resolve => { 
    setTimeout(resolve, 3000); 
    }); 
} 

async function serial() { 
    await sleep(); 
    await sleep(); 
} 

async function parallel() { 
    var a = sleep(); 
    var b = sleep(); 
    await a; 
    await b; 
} 

serial().then(() => { 
    console.log("6 seconds over"); 
}); 

parallel().then(() => { 
    console.log("3 seconds over"); 
}); 
+0

Dlaczego sądzisz, że "setTimeout" jest asynchroniczne? W twoim kodzie nie ma nic asynchronicznego poza deklaracjami funkcji. – Mjh

+3

@Mjh Errm, 'setTimeout' jest z natury bardzo asynchroniczny ... i prawie wszystko inne w kodzie OP jest również asynchroniczne ... – Frxstrem

+2

@Frxstrem oprócz' setTimeout' nie jest wcale asynchroniczny. Jest to funkcja synchroniczna, która mówi pętli zdarzeń, aby wykonała funkcję w późniejszym czasie.Jest to * mechanizm *, w tym kodzie absolutnie NIC NIE jest asynchroniczny. Które dwie ruchome części poruszają się z różnymi prędkościami, w różnych kontekstach wykonania? Zero. Dlatego ten kod wcale nie jest asynchroniczny. – Mjh

Odpowiedz

4

Frxstream ma już an excellent answer. Aby się na tym oprzeć i przedstawić pewną perspektywę:

Pierwszą rzeczą, którą należy rozpoznać, jest to, że obietnice są tworzone "na gorąco" - to znaczy, zanim doświadczysz obiektu obietnicy, jest już "w toku".

Drugą ważną koncepcją jest to, że await jest jak "asynchroniczne oczekiwanie" - to znaczy zatrzymuje wykonywanie tej funkcji, dopóki ta obietnica nie zostanie spełniona.

Funkcja otrzymuje zwrot obietnicy, a następnie (asynchronicznie) czeka na wypełnienie tej obietnicy. Po tym, jak obietnica kończy się 3 sekundy później, serial ponownie wywołuje sleep, otrzymuje obietnicę z powrotem, a następnie (asynchronicznie) czeka na wypełnienie tej obietnicy. Po zakończeniu tej obietnicy 3 sekundy później kończy się serial.

Funkcja parallel wzywa sleep i przechowuje swoją obietnicę w a, a następnie wywołuje sleep i przechowuje swoją obietnicę w b, a następnie (asynchronicznie) czeka na a aby zakończyć. Po wykonaniu a po 3 sekundach, parallel (asynchronicznie) czeka na zakończenie b. Po zakończeniu b praktycznie natychmiast kończy się parallel.

6

To jaśniejsze jeśli napiszesz swoją funkcję serial takiego:

async function serial() { 
    var a = sleep(); // 
    await a;   // await sleep(); 

    var b = sleep(); // 
    await b;   // await sleep(); 
} 

async function parallel() { 
    var a = sleep(); 
    var b = sleep(); 
    await a; 
    await b; 
} 

Tutaj można wyraźnie zobaczyć, że w funkcji serial, drugi sleep() nazywa się dopiero po pierwszym sleep() została zakończona, natomiast w parallel jest on wywoływany natychmiast, zanim pierwszy zostanie zakończony, a następnie oczekuje na zakończenie obydwu. Tak więc, chociaż mogą one wyglądać identycznie funkcjonalnie, są one subtelnie różne.

3

Ponieważ funkcja sleep() jest synchroniczny funkcja, to po prostu powrót do asynchronicznego obietnicę, np:

function sleep (time) { 
    return new Promise((resolve) => setTimeout(resolve, time)); 
} 

W parallel(), dwie sleep() synchronicznie startowych dwa obietnica, czekają zostać rozwiązane w międzyczasie, to będzie około 3s.

Jednak w serial(), dwa await sleep() oznacza, że ​​drugi sleep() obietnica musi czekać na pierwszy sleep() zostać rozwiązany, więc to będzie około 6s.

Powiązane problemy