javascript - Async/await ve then performans açısından hangisi en iyisidir?


JavaScript'te bir API isteği yapan ve yanıtı döndüren basit bir kodum var, basit. Ama bu durumda binlerce isteğim olacak. Peki, kod seçeneklerinden hangisi daha iyi performans gösterecek ve neden? Ayrıca günümüzde iyi uygulamalar olarak hangisi öneriliyor?

İlk seçenek, vaatleri çözmek için .then kullanmaktır ve ikinci seçenek ise async/await kullanmaktır.

Testlerimde iki seçenek çok benzer sonuçlar verdi, önemli bir fark olmadan, ama ölçek konusunda emin değilim.

// Using then
doSomething(payload) {
  const url = 'https://link-here/consultas';
  return this.axios.get(url, {
    params: {
      token: payload.token,
      chave: payload.chave,
    },
   }).then(resp => resp.data);
}

// Using Async / await
async doSomething(payload) {
   const url = 'https://link-here/consultas';
   const resp = await this.axios.get(url, {
   params: {
     token: payload.token,
     chave: payload.chave,
    },
 });
 return resp.data;
}

Her açıklama büyük değer taşıyacaktır.

Cevap #1

Performans açısından bakıldığında, await sadece .then()'in dahili bir versiyonudur (temelde aynı şeyi yapar). Birini diğerine tercih etme nedeni gerçekten performansla ilgili değil, istenen kodlama stili veya kodlama kolaylığı ile ilgilidir. Kesinlikle, yorumlayıcının await ile içsel olarak bazı şeyleri optimize etme fırsatları vardır, ancak hangi yöntemi kullanacağınıza karar verirken bu belirleyici olmamalıdır. Her şey eşitse, yukarıda belirtilen nedenle await'i seçerdim. Ama önce, kodu yazmayı, anlamayı, bakımını ve testini daha basit hale getiren yöntemi seçerdim.

Doğru kullanıldığında, await sıklıkla kodunuzun okunmasını, test edilmesini ve bakımını daha basit hale getirerek size bir sürü satır kod kazandırabilir. Bu yüzden icat edildi.

Kodunuzun iki sürümü arasında anlamlı bir fark yok. Her ikisi de axios çağrısı başarılı olduğunda veya hata verdiğinde aynı sonucu elde eder.

await'in daha faydalı olabileceği yer, birden çok ardışık asenkron çağrının sıralanması gerektiği durumdur. O zaman, her birini doğru şekilde zincirlemek için bir .then() işleyici içinde sınırlamak yerine, sadece await kullanabilir ve daha basit görünen bir kod elde edebilirsiniz.

await ve .then() ile yapılan yaygın bir hata, doğru hata yönetimini unutmaktır. Bu fonksiyonda hata yönetimi olarak sadece reddedilen promise'i döndürmek istiyorsanız, iki sürümünüz de bunu aynı şekilde yapar. Ancak, arka arkaya birden fazla async çağrı yapıyorsanız ve ilk reddi döndürmekten daha karmaşık bir şey yapmak istiyorsanız, await ile .then()/.catch() için hata yönetimi teknikleri oldukça farklıdır ve hangisinin daha basit göründüğü durumun kendisine bağlıdır.

Cevap #2

Bu dizide bazı düzeltmeler yapılmalıdır. await ve .then çok farklı sonuçlar verecek ve farklı nedenlerle kullanılmalıdır.

await bir şey için BEKLEYECEK ve sonra bir sonraki satıra devam edecektir. Ayrıca ikisinden daha basittir çünkü mekanik olarak eşzamanlı davranışa daha yakındır. Adım #1'i yaparsınız, beklersiniz ve sonra devam edersiniz.

console.log("Runs first.");
await SomeFunction();
console.log("Runs last.");

.then, orijinal çağrıdan ayrılır ve kendi kapsamı içinde işlem yapmaya başlar ve orijinal kapsamın tahmin edemeyeceği bir zamanda güncelleme yapar. Anlam bilgisini bir kenara bırakabilirsek, bu "daha asenkron"dur, çünkü eski kapsamdan çıkar ve yeni bir dala ayrılır.

console.log("Runs first.");
SomeFunction().then((value) => {console.log("Runs last (probably). Didn't use await on SomeFunction().")})
console.log("Runs second (probably).");

Cevap #3

Daha fazla açıklama olarak @user280209 cevabına, promise döndüren aşağıdaki fonksiyonu ele alalım ve yürütülmesini .then() ve async await ile karşılaştıralım.

function call(timeout) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(`This call took ${timeout} seconds`);
      resolve(true);
    }, timeout * 1000);
  });
}

.then() ile

(async () => {
  call(5).then((r) => {
    console.log(r);
  });
  await call(2); //This will print result first
  await call(1);
})();

Yukarıdaki çağrıyı çalıştırırken günlükler şunlar olacaktır

This call took 2 seconds
This call took 1 seconds
This call took 5 seconds
true

Gördüğümüz gibi .then() tamamlanana kadar altındaki satırın yürütmesini durdurmadı.

async/wait ile

(async () => {
  await call(5); //This will print result first
  await call(2); 
  await call(1);
})();

Yukarıdaki fonksiyon çalıştırıldığında kayıtlar şunlar olacaktır

This call took 5 seconds
This call took 2 seconds
This call took 1 seconds

Yani bence eğer sözünüzün sonucunun sonraki satırlarda kullanılmayacaksa, .then() daha iyi olabilir.

Cevap #4

Kodun async çağrı dönene kadar bloke olduğunu söyleyenler konuyu kaçırıyor. "await", bir promise.then() için sözdizimsel şekerleme gibidir. Aslında, sizin için oluşturduğu bir promise'in then bloğu içinde fonksiyonunuzun geri kalanını sarıyor. Gerçekte bir "bloklama" ya da "bekleme" yoktur.

run();

async function run() {
    console.log('running');
    makePromises();
    console.log('exiting right away!');
}

async function makePromises() {
    console.log('make promise 1');
    const myPromise = promiseMe(1)
    .then(msg => {
        console.log(`What i want to run after the promise is resolved ${msg}`)
    })
    console.log('make promise 2')
    const msg = await promiseMe(2);
    console.log(`What i want to run after the promise is resolved via await ${msg}`)
}   

function promiseMe(num: number): Promise<string> {
    return new Promise((resolve, reject) => {
        console.log(`promise`)
        resolve(`hello promise ${num}`);
    })
}

makePromises içindeki await satırı hiçbir şeyi engellemez ve çıktı şudur:

  • koşmak
  • söz ver 1
  • söz
  • söz ver 2
  • söz
  • hemen çıkıyor!
  • Söz yerine getirildiğinde çalıştırmak istediğim şey merhaba söz 1
  • Beklenen hello promise 2 çözülünce çalıştırmak istediğim şey

İlgili makaleler