Hur async/await och Promise fungerar i TypeScript


Jag har en liten funktion för att lära mig hur async, await och promise fungerar här.

function delay(ms: number) {
    return new Promise<void>(function(resolve) {
       setTimeout(resolve, ms);
    });
}

async function asyncAwait() {
    console.log("A");

    await delay(1000);
    console.log("B");

    await delay(1000);
    console.log("C");
}

asyncAwait();
console.log("D");

Min förståelse är att arbetsflödet skulle vara som,

anropa asyncAwait(); först, sedan skriv ut A, sedan vänta i 1 s och skriv ut B sedan vänta ytterligare 1 s och skriv ut C till sist skriv ut D.

men min utdata är som,

A
D
B
C

Jag vet inte varför console.log("D") visas som andra.

kan någon förklara koden ovan ?

tack på förhand

Svar #1

Det är så asynkrona samtal fungerar.

Hur du tror att kodkörningen är:

function delay(ms: number) {
    return new Promise<void>(function(resolve) {
       setTimeout(resolve, ms);
    });
}

async function asyncAwait() {
    console.log("A");

    await delay(1000);
    console.log("B");

    await delay(1000);
    console.log("C");
}

asyncAwait();   // <-- 1st call
console.log("D");

Sedan inuti den funktionen:

async function asyncAwait() {
    console.log("A");  // <--- 1st print, as it is synchronous

    await delay(1000); // <--- await
    console.log("B");  // <--- 2nd print

    await delay(1000); // <-- await
    console.log("C");  // <-- 3rd print
}

Och sedan till sist

function delay(ms: number) {
    return new Promise<void>(function(resolve) {
       setTimeout(resolve, ms);
    });
}

async function asyncAwait() {
    console.log("A");

    await delay(1000);
    console.log("B");

    await delay(1000);
    console.log("C");
}

asyncAwait();
console.log("D"); // <-- last print

MEN, den asynkrona funktionen är asynkron. Så alla asynkrona anrop går in i kön och behandlas senare.

Alltså, först körs de synkrona anropen:

console.log("A");
console.log("D");

Och sedan de asynkrona anropen.

await fungerar bara inom en async-funktion.

Så funktionen:

async function asyncFunc() {
  console.log("A");

  await delay(1000);
  console.log("B");
}

är ungefär motsvarande detta:

asyncFunc() {
  console.log('A');
  delay().then(()=> {
     console.log('B');
  });
}

Så om du vill att console.log("D") ska köras efter den asynkrona funktionen bör du använda await på asyncFunction. Men för att använda await måste du vara i en asynkron funktion:

async function asyncFunc2() {
  await asyncAwait();
  console.log("D");
}

asyncFunc2();

Svar #2

Du måste await för asyncAwait()-anropet:

function delay(ms: number) {
    return new Promise<void>(function(resolve) {
       setTimeout(resolve, ms);
    });
}

async function asyncAwait() {
    console.log("A");

    await delay(1000);
    console.log("B");

    await delay(1000);
    console.log("C");
}

async function main() {
    await asyncAwait();
    console.log("D");
}

main();