forEach/map ve async el ele gitmez

May 07 2023
Zaman zaman, zaman uyumsuz işlevleri forEach ve map işlevleriyle geçirme eğilimindeyiz. Örneğin: Sonuç: 1'den tüm sayılar.
Başlık

Zaman zaman, zaman uyumsuz işlevleri forEach ve map işlevleriyle geçirme eğilimindeyiz.

örneğin:

[1,2,3,4,5].forEach(async (n) => setTimeout(console.log(n), 1000));

Sonuç: 1..5'ten itibaren tüm sayılar arka arkaya yazdırılır ancak her satır yazdırıldıktan sonra 1 saniye boşluk kalmaz .

Bu neden oluyor?

Şu javascipt işlevine bakın:

async function doubleOf(n) {
  return n*2;
}

Sonuç: Bu aslında bir sayıya çözümlenen bir Promise döndürüyor.

Bu fonksiyonun bir TypeScript eşdeğerini katı tiplerle yazarsak, bu işleri netleştirecektir.

Aşağıdaki kod derlenmeyecek :

async function doubleOf(n: number): number {
  return n*2;
}

Doğru sürüm şöyle olacaktır:

async function doubleOf(n: number): Promise<number> {
  return n*2;
}

async-await tarafından sağlanan sözdizimsel şekere aldanmayın. Async kullanmadan saf vaatler yazsaydık, yukarıdaki işlev şöyle görünürdü:

function doubleOf(n) {
  return new Promise((resolve) => resolve(n*2));
}

function doubleOf(n: number): Promise<number> {
  return new Promise((resolve) => resolve(n*2));
}

zaman uyumsuz işlevler, değerleri değil vaatleri döndürür
  1. doubleOfBir sayı alan ve bir sayı döndüren bir fonksiyonumuz var . Düz eski javascript.
  2. doubleOfOldWayBir sayı alan ve bir sayıya çözümlenen bir söz veren bir işlevimiz var .
  3. doubleOfNewWayBir sayıyı alan ve bir sayı döndürüyormuş gibi görünen, ancak aslında tıpkı doubleOfOldWayişlev gibi bir sayıya çözümlenen bir söz veren bir zaman uyumsuz işlevimiz var .
  4. doubleOfOldWayve doubleOfNewWayfonksiyonlar tamamen aynıdır.
  5. doubleOfOldWayVe bu nedenle, ve işlevleri tarafından döndürülen değerler üzerinde bir çarpma işlemi yürütmeye çalıştığımızda , birden çok söz veremeyeceğimiz için (tabii ki!) doubleOfNewWaysonuç oldu .NaN
  6. çarpmak için doubleOfOldWayve doubleOfNewWay:

İlk örneğimize geri dönelim:

[1,2,3,4,5].forEach(async (n) => setTimeout(console.log(n), 1000));

Bu forEach işlevinden beklediğimizi uygulamanın en doğru yolu basit bir for döngüsü kullanmaktır:

for(const number of [1,2,3,4,5]) {
    console.log(number);
    await new Promise(resolve => setTimeout(resolve, 1000)); // Sleep for "atleast" 1 second
}

[1,2,3,4,5].map(async (n) => n*2);

(5) [Promise, Promise, Promise, Promise, Promise]
0: Promise {<fulfilled>: 2}
1: Promise {<fulfilled>: 4}
2: Promise {<fulfilled>: 6}
3: Promise {<fulfilled>: 8}
4: Promise {<fulfilled>: 10}

Her sayının iki katının bir listesini almak için yapabileceklerimiz:

await Promise.all([1,2,3,4,5].map(async (n) => n*2));

[2, 4, 6, 8, 10]