Eş zamansız işlevler: Vaatleri anlaşılır hale getirme

Asynchronize işlevler, promise tabanlı kodları zaman uyumluymuş gibi yazmanıza olanak tanır.

Jake Archibald
Jake Archibald

Asenkron işlevler Chrome, Edge, Firefox ve Safari'de varsayılan olarak etkindir ve gerçekten muhteşemdir. Bu yöntemler, ana iş parçacığı engellenmeden, söze dayalı kodu sanki eşzamanlıymış gibi yazmanıza olanak tanır. Asenkron kodunuzu daha az "zeki" ve daha okunaklı hale getirirler.

Eş zamansız işlevler şu şekilde çalışır:

async function myFirstAsyncFunction() {
  try {
    const fulfilledValue = await promise;
  } catch (rejectedValue) {
    // …
  }
}

Bir işlev tanımından önce async anahtar kelimesini kullanırsanız işlev içinde await kullanabilirsiniz. Bir await söz verdiğiniz zaman işlev, söz yerine gelene kadar engellenmeyen bir şekilde duraklatılır. Söz verilen işlem gerçekleşirse değeri geri alırsınız. Sözleşme reddedilirse reddedilen değer atılır.

Tarayıcı desteği

Browser Support

  • Chrome: 55.
  • Edge: 15.
  • Firefox: 52.
  • Safari: 10.1.

Source

Örnek: Getirme işlemini günlüğe kaydetme

Bir URL almak ve yanıtı metin olarak günlüğe kaydetmek istediğinizi varsayalım. Söz vererek bu işlemi aşağıdaki gibi yapabilirsiniz:

function logFetch(url) {
  return fetch(url)
    .then((response) => response.text())
    .then((text) => {
      console.log(text);
    })
    .catch((err) => {
      console.error('fetch failed', err);
    });
}

Aşağıda, aynı işlemler asynkron işlevler kullanılarak gösterilmiştir:

async function logFetch(url) {
  try {
    const response = await fetch(url);
    console.log(await response.text());
  } catch (err) {
    console.log('fetch failed', err);
  }
}

Satır sayısı aynıdır ancak tüm geri aramalar kaldırılmıştır. Bu sayede, özellikle de vaatler hakkında daha az bilgi sahibi olanlar için okumak çok daha kolay olur.

Eşzamansız döndürülen değerler

await kullanıp kullanmadığınıza bakılmaksızın, asynkron işlevler her zaman bir promise döndürür. Bu söz, asynkron işlevin döndürdüğü değerle çözülür veya asynkron işlevin oluşturduğu hatayla reddedilir. Bu nedenle:

// wait ms milliseconds
function wait(ms) {
  return new Promise((r) => setTimeout(r, ms));
}

async function hello() {
  await wait(500);
  return 'world';
}

hello() çağrısı, "world" ile yerine getirilen bir söz döndürür.

async function foo() {
  await wait(500);
  throw Error('bar');
}

foo() çağrısı, Error('bar') ile rejects bir promise döndürür.

Örnek: Yanıtı akış şeklinde gönderme

Asenkron işlevlerin avantajı, daha karmaşık örneklerde artar. Parçaları günlüğe kaydederken bir yanıtı aktarmak ve nihai boyutu döndürmek istediğinizi varsayalım.

Sözlerimizi yerine getiriyoruz:

function getResponseSize(url) {
  return fetch(url).then((response) => {
    const reader = response.body.getReader();
    let total = 0;

    return reader.read().then(function processResult(result) {
      if (result.done) return total;

      const value = result.value;
      total += value.length;
      console.log('Received chunk', value);

      return reader.read().then(processResult);
    });
  });
}

Ben Jake "söz veren" Archibald. Asenkron bir döngü oluşturmak için processResult() işlevini kendi içinde nasıl çağırdığımı görüyor musunuz? Bu yazı beni çok akıllı hissettirdi. Ancak çoğu "akıllı" kod gibi, ne yaptığını anlamak için saatlerce bakmanız gerekir. 90'lardaki sihirli göz resimlerinden biri gibi.

Bunu tekrar asenkron işlevlerle deneyelim:

async function getResponseSize(url) {
  const response = await fetch(url);
  const reader = response.body.getReader();
  let