javascript - Istovremeni početak s async/await


Mislio sam da imam prilično dobro razumijevanje async await dok ovo nisam pokušao:

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('what'), 10000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('?'), 15000);
});

async function asyncTest() {
  console.time();
  const p1 = await promise1;

  if (p1 === 'what') {
    var p2 = await promise2;
  }

  console.log(p1, p2);
  console.timeEnd();
}

asyncTest()

Nakon 15000 ms, asyncTest zapisuje p1 i p2. Ako se umjesto toga promise1 i promise2 pretvore u funkcije koje vraćaju te promise-ove, vrijeme izvršenja je tada 25000 ms. Nemam pojma što se događa. Može li netko objasniti ovo?

Odgovor #1

Problem je u tome što se vaši Promise pozivi vraćaju odmah nakon što ih deklarirate.

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('what'), 10000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('?'), 15000);
});

U ovom trenutku obje povratne funkcije su pozvane. 10000 ms od ovog trenutka, promise1 će biti riješen. 15000 ms od ovog trenutka, promise2 će biti riješen.

async function asyncTest() {
  console.time();
  const p1 = await promise1;

  if (p1 === 'what') {
    var p2 = await promise2;
  }

  console.log(p1, p2);
  console.timeEnd();
}

asyncTest()

U ovom trenutku, budući da su oba povratna poziva već pozvana, oba će biti riješena unutar 15000 ms, što ste i primijetili.

Kako biste ovo produžili na 25000 ms koje ste očekivali, pokušajte prepisati Promises na sljedeći način:

const promise1 = () => new Promise((resolve, reject) => {
  setTimeout(() => resolve('what'), 10000);
});

const promise2 = () => new Promise((resolve, reject) => {
  setTimeout(() => resolve('?'), 15000);
});

Napomena, ovo su sada funkcijske izraze koje neće biti odmah pozvane. Zatim prepišite svoju asyncTest funkciju kako bi pozivala ove izraze umjesto da jednostavno čeka već izvršavajuće Promise:

async function asyncTest() {
  console.time();
  const p1 = await promise1();

  if (p1 === 'what') {
    var p2 = await promise2();
  }

  console.log(p1, p2);
  console.timeEnd();
}

Ovo će prisiliti promise2 da čeka dok promise1 ne bude dovršen prije nego što započne izvršavanje.

Odgovor #2

S kodom u njegovom trenutnom stanju:

Pokrenete setTimeout i dodijelite obećanje koje će obraditi njegov rezultat u promise1. Neposredno nakon toga, učinite isto za promise2.

Dakle, promise2 se rješava otprilike pet sekundi nakon promise1.

Ako promijenite kod tako da su promise1 i promise2 funkcije, tada:

Pokrenete setTimeout koji vraća obećanje koje će svoje rezultate obraditi u await. Čekat će dok se obećanje ne riješi 10 sekundi kasnije. Zatim će dodijeliti rezultat u p1.

Zatim (tj. nakon što prođe 10 sekundi umjesto odmah) učinit će isto za p2.

Ukratko:

U prvom primjeru, ne čekate promise1 prije nego što pokrenete promise2.

Nakon što napravite promjenu koju opisujete, radite await na promise1 prije nego što postavite da promise2 krene.