Π Π°Π·Π±ΠΈΡ€Π°Π΅ΠΌ Async/Await Π² JavaScript Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ…

Автор ΡΡ‚Π°Ρ‚ΡŒΠΈ Ρ€Π°Π·Π±ΠΈΡ€Π°Π΅Ρ‚ Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ… Async/Await Π² JavaScript. Π’ Ρ†Π΅Π»ΠΎΠΌ, Async/Await β€” ΡƒΠ΄ΠΎΠ±Π½Ρ‹ΠΉ способ написания асинхронного ΠΊΠΎΠ΄Π°. Π”ΠΎ появлСния этой возмоТности ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ писали с использованиСм коллбэков ΠΈ промисов. Автор ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠΉ ΡΡ‚Π°Ρ‚ΡŒΠΈ раскрываСт прСимущСства Async/Await, разбирая Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹.

НапоминаСм: для всСх Ρ‡ΠΈΡ‚Π°Ρ‚Π΅Π»Π΅ΠΉ Β«Π₯Π°Π±Ρ€Π°Β» β€” скидка 10 000 Ρ€ΡƒΠ±Π»Π΅ΠΉ ΠΏΡ€ΠΈ записи Π½Π° любой курс Skillbox ΠΏΠΎ ΠΏΡ€ΠΎΠΌΠΎΠΊΠΎΠ΄Ρƒ Β«Π₯Π°Π±Ρ€Β».

Skillbox Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΠ΅Ρ‚: ΠžΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΎΠ½Π»Π°ΠΉΠ½-курс Β«Java-Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΒ».

Callback

Callback прСдставляСт собой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, Π²Ρ‹Π·ΠΎΠ² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½ Π½Π° Π½Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ΅ врСмя. РаньшС ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Π΅ Π²Ρ‹Π·ΠΎΠ²Ρ‹ использовались Π² Ρ‚Π΅Ρ… участках ΠΊΠΎΠ΄Π°, Π³Π΄Π΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π½Π΅ ΠΌΠΎΠ³ Π±Ρ‹Ρ‚ΡŒ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ сразу.

Π’ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ асинхронного чтСния Ρ„Π°ΠΉΠ»Π° Π½Π° Node.js:

fs.readFile(__filename, 'utf-8', (err, data) => {
  if (err) {
    throw err;
  }
  console.log(data);
});

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ Π²ΠΎΠ·Π½ΠΈΠΊΠ°ΡŽΡ‚ Π² Ρ‚ΠΎΡ‚ ΠΌΠΎΠΌΠ΅Π½Ρ‚, ΠΊΠΎΠ³Π΄Π° трСбуСтся Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ сразу нСсколько асинхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Π”Π°Π²Π°ΠΉΡ‚Π΅ прСдставим сСбС Π²ΠΎΡ‚ Ρ‚Π°ΠΊΠΎΠΉ сцСнарий: выполняСтся запрос Π² Π‘Π” ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ Arfat, Π½ΡƒΠΆΠ½ΠΎ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ Π΅Π³ΠΎ ΠΏΠΎΠ»Π΅ profile_img_url ΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΈΡ‚ΡŒ ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΡƒ с сСрвСра someserver.com.
ПослС Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ ΠΊΠΎΠ½Π²Π΅Ρ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π² ΠΈΠ½ΠΎΠΉ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΈΠ· PNG Π² JPEG. Если конвСртация ΠΏΡ€ΠΎΡˆΠ»Π° ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ, Π½Π° ΠΏΠΎΡ‡Ρ‚Ρƒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ отправляСтся письмо. Π”Π°Π»Π΅Π΅ информация ΠΎ событии заносится Π² Ρ„Π°ΠΉΠ» transformations.log с ΡƒΠΊΠ°Π·Π°Π½ΠΈΠ΅ΠΌ Π΄Π°Ρ‚Ρ‹.

Π‘Ρ‚ΠΎΠΈΡ‚ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Π½Π°Π»ΠΎΠΆΠ΅Π½Π½ΠΎΡΡ‚ΡŒ ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² ΠΈ большоС количСство }) Π² Ρ„ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠΉ части ΠΊΠΎΠ΄Π°. Π­Ρ‚ΠΎ называСтся Callback Hell ΠΈΠ»ΠΈ Pyramid of Doom.

НСдостатки Ρ‚Π°ΠΊΠΎΠ³ΠΎ способа ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½Ρ‹:

  • Π­Ρ‚ΠΎΡ‚ ΠΊΠΎΠ΄ слоТно Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ.
  • Π’ Π½Π΅ΠΌ Ρ‚Π°ΠΊΠΆΠ΅ слоТно ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ ошибки, Ρ‡Ρ‚ΠΎ Π·Π°Ρ‡Π°ΡΡ‚ΡƒΡŽ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ ΡƒΡ…ΡƒΠ΄ΡˆΠ΅Π½ΠΈΡŽ качСства ΠΊΠΎΠ΄Π°.

Для Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ эту ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ, Π² JavaScript Π±Ρ‹Π»ΠΈ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Ρ‹ промисы. Они ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π³Π»ΡƒΠ±ΠΎΠΊΡƒΡŽ Π²Π»ΠΎΠΆΠ΅Π½Π½ΠΎΡΡ‚ΡŒ коллбэков словом .then.

ΠŸΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ ΠΌΠΎΠΌΠ΅Π½Ρ‚ΠΎΠΌ промисов стало Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ с Π½ΠΈΠΌΠΈ ΠΊΠΎΠ΄ читаСтся Π³ΠΎΡ€Π°Π·Π΄ΠΎ Π»ΡƒΡ‡ΡˆΠ΅, ΠΏΡ€ΠΈΡ‡Π΅ΠΌ свСрху Π²Π½ΠΈΠ·, Π° Π½Π΅ слСва Π½Π°ΠΏΡ€Π°Π²ΠΎ. Π’Π΅ΠΌ Π½Π΅ ΠΌΠ΅Π½Π΅Π΅ Ρƒ промисов Ρ‚ΠΎΠΆΠ΅ Π΅ΡΡ‚ΡŒ свои ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹:

  • НуТно Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ большоС количСство .then.
  • ВмСсто try/catch ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ .catch для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ всСх ошибок.
  • Π Π°Π±ΠΎΡ‚Π° с нСсколькими промисами Π² Ρ€Π°ΠΌΠΊΠ°Ρ… ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ†ΠΈΠΊΠ»Π° Π΄Π°Π»Π΅ΠΊΠΎ Π½Π΅ всСгда ΡƒΠ΄ΠΎΠ±Π½Π°, Π² Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… случаях ΠΎΠ½ΠΈ ΡƒΡΠ»ΠΎΠΆΠ½ΡΡŽΡ‚ ΠΊΠΎΠ΄.

Π’ΠΎΡ‚ Π·Π°Π΄Π°Ρ‡Π°, которая ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ послСднСго ΠΏΡƒΠ½ΠΊΡ‚Π°.

ΠŸΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, Ρ‡Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Ρ†ΠΈΠΊΠ» for, выводящий ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ чисСл ΠΎΡ‚ 0 Π΄ΠΎ 10 со случайным ΠΈΠ½Ρ‚Π΅Ρ€Π²Π°Π»ΠΎΠΌ (0–n сСкунд). Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ промисы, Π½ΡƒΠΆΠ½ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ этот Ρ†ΠΈΠΊΠ» Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ числа Π²Ρ‹Π²ΠΎΠ΄ΠΈΠ»ΠΈΡΡŒ Π² ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ ΠΎΡ‚ 0 Π΄ΠΎ 10. Π’Π°ΠΊ, Ссли Π²Ρ‹Π²ΠΎΠ΄ нуля Π·Π°Π½ΠΈΠΌΠ°Π΅Ρ‚ 6 сСкунд, Π° Π΅Π΄ΠΈΠ½ΠΈΡ†Ρ‹ β€” 2 сСкунды, сначала Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ Π²Ρ‹Π²Π΅Π΄Π΅Π½ ноль, Π° ΠΏΠΎΡ‚ΠΎΠΌ ΡƒΠΆΠ΅ начнСтся отсчСт Π²Ρ‹Π²ΠΎΠ΄Π° Π΅Π΄ΠΈΠ½ΠΈΡ†Ρ‹.

И ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎ, для Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ этой Π·Π°Π΄Π°Ρ‡ΠΈ ΠΌΡ‹ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Async/Await Π»ΠΈΠ±ΠΎ .sort. ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ β€” Π² ΠΊΠΎΠ½Ρ†Π΅.

Async-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ

Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ async-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ Π² ES2017 (ES8) упростило Π·Π°Π΄Π°Ρ‡Ρƒ Ρ€Π°Π±ΠΎΡ‚Ρ‹ с промисами. ΠžΡ‚ΠΌΠ΅Ρ‡Ρƒ, Ρ‡Ρ‚ΠΎ async-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ Β«ΠΏΠΎΠ²Π΅Ρ€Ρ…Β» промисов. Π­Ρ‚ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π΅ ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‚ собой качСствСнно Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΠΈ. Async-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π·Π°Π΄ΡƒΠΌΡ‹Π²Π°Π»ΠΈΡΡŒ ΠΊΠ°ΠΊ Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π° ΠΊΠΎΠ΄Ρƒ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ промисы.

Async/Await Π΄Π°Π΅Ρ‚ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΎΡ€Π³Π°Π½ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρƒ с асинхронным ΠΊΠΎΠ΄ΠΎΠΌ Π² синхронном стилС.

Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Π·Π½Π°Π½ΠΈΠ΅ промисов ΠΎΠ±Π»Π΅Π³Ρ‡Π°Π΅Ρ‚ ΠΏΠΎΠ½ΠΈΠΌΠ°Π½ΠΈΠ΅ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠΎΠ² Async/Await.

Бинтаксис

Π’ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠΉ ситуации ΠΎΠ½ состоит ΠΈΠ· Π΄Π²ΡƒΡ… ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Ρ… слов: async ΠΈ await. ΠŸΠ΅Ρ€Π²ΠΎΠ΅ слово ΠΈ ΠΏΡ€Π΅Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ Π² Π°ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΡƒΡŽ. Π’ Ρ‚Π°ΠΊΠΈΡ… функциях Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ΡΡ использованиС await. Π’ любом Π΄Ρ€ΡƒΠ³ΠΎΠΌ случаС использованиС этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅Ρ‚ ΠΎΡˆΠΈΠ±ΠΊΡƒ.

// With function declaration
 
async function myFn() {
  // await ...
}
 
// With arrow function
 
const myFn = async () => {
  // await ...
}
 
function myFn() {
  // await fn(); (Syntax Error since no async)
}
 

Async вставляСтся Π² самом Π½Π°Ρ‡Π°Π»Π΅ объявлСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π° Π² случаС использования стрСлочной Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ β€” ΠΌΠ΅ΠΆΠ΄Ρƒ Π·Π½Π°ΠΊΠΎΠΌ Β«=Β» ΠΈ скобками.

Π­Ρ‚ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ Π² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π² качСствС ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² Π»ΠΈΠ±ΠΎ ΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² объявлСнии класса.

// As an object's method
 
const obj = {
  async getName() {
    return fetch('https://www.example.com');
  }
}
 
// In a class
 
class Obj {
  async getResource() {
    return fetch('https://www.example.com');
  }
}

NB! Π‘Ρ‚ΠΎΠΈΡ‚ ΠΏΠΎΠΌΠ½ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ конструкторы класса ΠΈ Π³Π΅Ρ‚Ρ‚Π΅Ρ€Ρ‹/сСттСры Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ асинхронными.

Π‘Π΅ΠΌΠ°Π½Ρ‚ΠΈΠΊΠ° ΠΈ ΠΏΡ€Π°Π²ΠΈΠ»Π° выполнСния

Async-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π² ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΠ΅, ΠΏΠΎΡ…ΠΎΠΆΠΈ Π½Π° стандартныС JS-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π½ΠΎ Π΅ΡΡ‚ΡŒ ΠΈ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ.

Π’Π°ΠΊ, async-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ всСгда Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ промисы:

async function fn() {
  return 'hello';
}
fn().then(console.log)
// hello

Π’ частности, fn Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ строку hello. Ну Π° ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ это асинхронная функция, Ρ‚ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ строки обСртываСтся Π² промис ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ конструктора.

Π’ΠΎΡ‚ Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π½Π°Ρ конструкция Π±Π΅Π· Async:

function fn() {
  return Promise.resolve('hello');
}
 
fn().then(console.log);
// hello

Π’ этом случаС Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ промиса производится Β«Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽΒ». Асинхронная функция всСгда обСртываСтся Π² Π½ΠΎΠ²Ρ‹ΠΉ промис.

Π’ Ρ‚ΠΎΠΌ случаС, Ссли Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ β€” ΠΏΡ€ΠΈΠΌΠΈΡ‚ΠΈΠ², async-функция выполняСт Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ значСния, обСртывая Π΅Π³ΠΎ Π² промис. Π’ Ρ‚ΠΎΠΌ случаС, Ссли Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈ Π΅ΡΡ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ промиса, Π΅Π³ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ возвращаСтся Π² Π½ΠΎΠ²ΠΎΠΌ промисС.

const p = Promise.resolve('hello')
p instanceof Promise;
// true
 
Promise.resolve(p) === p;
// true
 

Но Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚ Π² Ρ‚ΠΎΠΌ случаС, Ссли Π²Π½ΡƒΡ‚Ρ€ΠΈ асинхронной Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ окаТСтся ошибка?

async function foo() {
  throw Error('bar');
}
 
foo().catch(console.log);

Если ΠΎΠ½Π° Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π½Π°, foo() Π²Π΅Ρ€Π½Π΅Ρ‚ промис с Ρ€Π΅Π΄ΠΆΠ΅ΠΊΡ‚ΠΎΠΌ. Π’ этой ситуации вмСсто Promise.resolve вСрнСтся Promise.reject, содСрТащий ΠΎΡˆΠΈΠ±ΠΊΡƒ.

Async-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π° Π²Ρ‹Ρ…ΠΎΠ΄Π΅ всСгда Π΄Π°ΡŽΡ‚ промис, Π²Π½Π΅ зависимости ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ возвращаСтся.

АсинхронныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΏΡ€ΠΈΠΎΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°ΡŽΡ‚ΡΡ ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ await .

Await влияСт Π½Π° выраТСния. Π’Π°ΠΊ, Ссли Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ являСтся промисом, async-функция приостанавливаСтся Π΄ΠΎ ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° выполнСния промиса. Π’ Ρ‚ΠΎΠΌ случаС, Ссли Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π½Π΅ являСтся промисом, ΠΎΠ½ΠΎ конвСртируСтся Π² промис Ρ‡Π΅Ρ€Π΅Π· Promise.resolve ΠΈ ΠΏΠΎΡ‚ΠΎΠΌ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ.

// utility function to cause delay
// and get random value
 
const delayAndGetRandom = (ms) => {
  return new Promise(resolve => setTimeout(
    () => {
      const val = Math.trunc(Math.random() * 100);
      resolve(val);
    }, ms
  ));
};
 
async function fn() {
  const a = await 9;
  const b = await delayAndGetRandom(1000);
  const c = await 5;
  await delayAndGetRandom(1000);
 
  return a + b * c;
}
 
// Execute fn
fn().then(console.log);

А Π²ΠΎΡ‚ описаниС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ fn-функция.

  • ПослС Π΅Π΅ Π²Ρ‹Π·ΠΎΠ²Π° пСрвая строка конвСртируСтся ΠΈΠ· const a = await 9; Π² const a = await Promise.resolve(9);.
  • ПослС использования Await Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ приостанавливаСтся, ΠΏΠΎΠΊΠ° Π° Π½Π΅ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ своС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ (Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ситуации это 9).
  • delayAndGetRandom(1000) приостанавливаСт Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ fn-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΏΠΎΠΊΠ° Π½Π΅ Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡΡ сама (послС 1 сСкунды). Π­Ρ‚ΠΎ фактичСски являСтся остановкой fn-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π° 1 сСкунду.
  • delayAndGetRandom(1000) Ρ‡Π΅Ρ€Π΅Π· resolve Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ случайноС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π·Π°Ρ‚Π΅ΠΌ присваиваСтся ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ b.
  • Ну Π° случай с ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ с Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π΅Π½ ΡΠ»ΡƒΡ‡Π°ΡŽ с ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ Π°. ПослС этого всС останавливаСтся Π½Π° сСкунду, Π½ΠΎ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ delayAndGetRandom(1000) Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ этого Π½Π΅ трСбуСтся.
  • Π’ ΠΈΡ‚ΠΎΠ³Π΅ значСния ΡΡ‡ΠΈΡ‚Π°ΡŽΡ‚ΡΡ ΠΏΠΎ Ρ„ΠΎΡ€ΠΌΡƒΠ»Π΅ a + b * c. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΆΠ΅ обСртываСтся Π² промис ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ Promise.resolve ΠΈ возвращаСтся Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ.

Π­Ρ‚ΠΈ ΠΏΠ°ΡƒΠ·Ρ‹ ΠΌΠΎΠ³ΡƒΡ‚ Π½Π°ΠΏΠΎΠΌΠΈΠ½Π°Ρ‚ΡŒ Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ Π² ES6, Π½ΠΎ этому Π΅ΡΡ‚ΡŒ свои ΠΏΡ€ΠΈΡ‡ΠΈΠ½Ρ‹.

РСшаСм Π·Π°Π΄Π°Ρ‡Ρƒ

Ну Π° Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π΄Π°Π²Π°ΠΉΡ‚Π΅ рассмотрим Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π·Π°Π΄Π°Ρ‡ΠΈ, которая Π±Ρ‹Π»Π° ΡƒΠΊΠ°Π·Π°Π½Π° Π²Ρ‹ΡˆΠ΅.

Π’ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ finishMyTask ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Await для оТидания Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Ρ‚Π°ΠΊΠΈΡ… ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ, ΠΊΠ°ΠΊ queryDatabase, sendEmail, logTaskInFile ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΡ…. Если ΠΆΠ΅ ΡΡ€Π°Π²Π½ΠΈΠ²Π°Ρ‚ΡŒ это Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ с Ρ‚Π΅ΠΌ, Π³Π΄Π΅ использовались промисы, станСт ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½Ρ‹ΠΌ сходство. Π’Π΅ΠΌ Π½Π΅ ΠΌΠ΅Π½Π΅Π΅ вСрсия с Async/Await довольно сильно ΡƒΠΏΡ€ΠΎΡ‰Π°Π΅Ρ‚ всС синтаксичСскиС слоТности. Π’ этом случаС Π½Π΅Ρ‚ большого количСства коллбэков ΠΈ Ρ†Π΅ΠΏΠΎΡ‡Π΅ΠΊ Π²Ρ€ΠΎΠ΄Π΅ .then/.catch.

Π’ΠΎΡ‚ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ с Π²Ρ‹Π²ΠΎΠ΄ΠΎΠΌ чисСл, здСсь Π΅ΡΡ‚ΡŒ Π΄Π²Π° Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π°.

const wait = (i, ms) => new Promise(resolve => setTimeout(() => resolve(i), ms));
 
// Implementation One (Using for-loop)
const printNumbers = () => new Promise((resolve) => {
  let pr = Promise.resolve(0);
  for (let i = 1; i <= 10; i += 1) {
    pr = pr.then((val) => {
      console.log(val);
      return wait(i, Math.random() * 1000);
    });
  }
  resolve(pr);
});
 
// Implementation Two (Using Recursion)
 
const printNumbersRecursive = () => {
  return Promise.resolve(0).then(function processNextPromise(i) {
 
    if (i === 10) {
      return undefined;
    }
 
    return wait(i, Math.random() * 1000).then((val) => {
      console.log(val);
      return processNextPromise(i + 1);
    });
  });
};

А Π²ΠΎΡ‚ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ с использованиСм async-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ.

async function printNumbersUsingAsync() {
  for (let i = 0; i < 10; i++) {
    await wait(i, Math.random() * 1000);
    console.log(i);
  }
}

ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ошибок

НСобработанныС ошибки ΠΎΠ±Π΅Ρ€Ρ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ Π² rejected промис. Π’Π΅ΠΌ Π½Π΅ ΠΌΠ΅Π½Π΅Π΅ Π² async-функциях ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡŽ try/catch для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΡƒΡŽ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ ошибок.

async function canRejectOrReturn() {
  // wait one second
  await new Promise(res => setTimeout(res, 1000));
 
// Reject with ~50% probability
  if (Math.random() > 0.5) {
    throw new Error('Sorry, number too big.')
  }
 
return 'perfect number';
}

canRejectOrReturn() β€” это асинхронная функция, которая Π»ΠΈΠ±ΠΎ ΡƒΠ΄Π°Ρ‡Π½ΠΎ выполняСтся (β€œperfect number”), Π»ΠΈΠ±ΠΎ Π½Π΅ΡƒΠ΄Π°Ρ‡Π½ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ с ошибкой (β€œSorry, number too big”).

async function foo() {
  try {
    await canRejectOrReturn();
  } catch (e) {
    return 'error caught';
  }
}

ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ Π²Ρ‹ΡˆΠ΅ оТидаСтся Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ canRejectOrReturn, Ρ‚ΠΎ собствСнноС Π½Π΅ΡƒΠ΄Π°Ρ‡Π½ΠΎΠ΅ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅ ΠΏΠΎΠ²Π»Π΅Ρ‡Π΅Ρ‚ Π·Π° собой исполнСниС Π±Π»ΠΎΠΊΠ° catch. Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ функция foo Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡΡ Π»ΠΈΠ±ΠΎ с undefined (ΠΊΠΎΠ³Π΄Π° Π² Π±Π»ΠΎΠΊΠ΅ try Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ возвращаСтся), Π»ΠΈΠ±ΠΎ с error caught. Π’ ΠΈΡ‚ΠΎΠ³Π΅ Ρƒ этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Π½Π΅ΡƒΠ΄Π°Ρ‡Π½ΠΎΠ³ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ try/catch займСтся ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ самой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ foo.

Π’ΠΎΡ‚ Π΅Ρ‰Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€:

async function foo() {
  try {
    return canRejectOrReturn();
  } catch (e) {
    return 'error caught';
  }
}

Π‘Ρ‚ΠΎΠΈΡ‚ ΡƒΠ΄Π΅Π»ΠΈΡ‚ΡŒ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Ρ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΈΠ· foo возвращаСтся canRejectOrReturn. Foo Π² этом случаС Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ Π»ΠΈΠ±ΠΎ perfect number, Π»ΠΈΠ±ΠΎ возвращаСтся ошибка Error (β€œSorry, number too big”). Π‘Π»ΠΎΠΊ catch Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΡΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ.

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ foo Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ промис, ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹ΠΉ ΠΎΡ‚ canRejectOrReturn. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ foo становится Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ΠΌ для canRejectOrReturn. Π’ этом случаС ΠΊΠΎΠ΄ Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΡΡ‚ΠΎΡΡ‚ΡŒ всСго ΠΈΠ· Π΄Π²ΡƒΡ… строк:

try {
    const promise = canRejectOrReturn();
    return promise;
}

А Π²ΠΎΡ‚ Ρ‡Ρ‚ΠΎ Π±ΡƒΠ΄Π΅Ρ‚, Ссли ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ вмСстС await ΠΈ return:

async function foo() {
  try {
    return await canRejectOrReturn();
  } catch (e) {
    return 'error caught';
  }
}

Π’ ΠΊΠΎΠ΄Π΅ Π²Ρ‹ΡˆΠ΅ foo ΡƒΠ΄Π°Ρ‡Π½ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡΡ ΠΊΠ°ΠΊ с perfect number, Ρ‚Π°ΠΊ ΠΈ с error caught. Π—Π΄Π΅ΡΡŒ ΠΎΡ‚ΠΊΠ°Π·ΠΎΠ² Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚. Но foo Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡΡ с canRejectOrReturn, Π° Π½Π΅ с undefined. Π”Π°Π²Π°ΠΉΡ‚Π΅ убСдимся Π² этом, ΡƒΠ±Ρ€Π°Π² строку return await canRejectOrReturn():

try {
    const value = await canRejectOrReturn();
    return value;
}
// …

РаспространСнныС ошибки ΠΈ ΠΏΠΎΠ΄Π²ΠΎΠ΄Π½Ρ‹Π΅ ΠΊΠ°ΠΌΠ½ΠΈ

Π’ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… случаях использованиС Async/Await ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ΡŒ ΠΊ ошибкам.

Π—Π°Π±Ρ‹Ρ‚Ρ‹ΠΉ await

Π’Π°ΠΊΠΎΠ΅ случаСтся достаточно часто β€” ΠΏΠ΅Ρ€Π΅Π΄ промисом забываСтся ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ слово await:

async function foo() {
  try {
    canRejectOrReturn();
  } catch (e) {
    return 'caught';
  }
}

Π’ ΠΊΠΎΠ΄Π΅, ΠΊΠ°ΠΊ Π²ΠΈΠ΄Π½ΠΎ, Π½Π΅Ρ‚ Π½ΠΈ await, Π½ΠΈ return. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ foo всСгда Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ с undefined Π±Π΅Π· Π·Π°Π΄Π΅Ρ€ΠΆΠΊΠΈ Π² 1 сСкунду. Но промис Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒΡΡ. Если ΠΆΠ΅ ΠΎΠ½ Π²Ρ‹Π΄Π°Π΅Ρ‚ ΠΎΡˆΠΈΠ±ΠΊΡƒ ΠΈΠ»ΠΈ Ρ€Π΅Π΄ΠΆΠ΅ΠΊΡ‚, Ρ‚ΠΎ Π² этом случаС Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒΡΡ UnhandledPromiseRejectionWarning.

Async-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²Π°Ρ…

Async-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ довольно часто ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Π² .map ΠΈΠ»ΠΈ .filter Π² качСствС коллбэков. Π’ качСствС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° ΠΌΠΎΠΆΠ½ΠΎ привСсти Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ fetchPublicReposCount(username), которая Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ количСство ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹Ρ… Π½Π° GitHub Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠ΅Π². Допустим, Π΅ΡΡ‚ΡŒ Ρ‚Ρ€ΠΈ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ, Ρ‡ΡŒΠΈ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ Π½Π°ΠΌ Π½ΡƒΠΆΠ½Ρ‹. Π’ΠΎΡ‚ ΠΊΠΎΠ΄ для этой Π·Π°Π΄Π°Ρ‡ΠΈ:

const url = 'https://api.github.com/users';
 
// Utility fn to fetch repo counts
const fetchPublicReposCount = async (username) => {
  const response = await fetch(`${url}/${username}`);
  const json = await response.json();
  return json['public_repos'];
}

Нам Π½ΡƒΠΆΠ½Ρ‹ Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚Ρ‹ ArfatSalman, octocat, norvig. Π’ этом случаС выполняСм:

const users = [
  'ArfatSalman',
  'octocat',
  'norvig'
];
 
const counts = users.map(async username => {
  const count = await fetchPublicReposCount(username);
  return count;
});

Π‘Ρ‚ΠΎΠΈΡ‚ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Await Π² ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠΌ Π²Ρ‹Π·ΠΎΠ²Π΅ .map. Π—Π΄Π΅ΡΡŒ counts β€” массив промисов, Π½Ρƒ Π° .map β€” Π°Π½ΠΎΠ½ΠΈΠΌΠ½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹ΠΉ Π²Ρ‹Π·ΠΎΠ² для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ.

Π§Ρ€Π΅Π·ΠΌΠ΅Ρ€Π½ΠΎ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ использованиС await

Π’ качСствС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° возьмСм Ρ‚Π°ΠΊΠΎΠΉ ΠΊΠΎΠ΄:

async function fetchAllCounts(users) {
  const counts = [];
  for (let i = 0; i < users.length; i++) {
    const username = users[i];
    const count = await fetchPublicReposCount(username);
    counts.push(count);
  }
  return counts;
}

Π—Π΄Π΅ΡΡŒ Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ count помСщаСтся число Ρ€Π΅ΠΏΠΎ, Π·Π°Ρ‚Π΅ΠΌ это число добавляСтся Π² массив counts. ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° ΠΊΠΎΠ΄Π° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ ΠΏΠΎΠΊΠ° с сСрвСра Π½Π΅ ΠΏΡ€ΠΈΠ΄ΡƒΡ‚ Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ, всС ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Π½Π°Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ оТидания. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Π² Π΅Π΄ΠΈΠ½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ обрабатываСтся лишь ΠΎΠ΄ΠΈΠ½ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ.

Если, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π½Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ ΡƒΡ…ΠΎΠ΄ΠΈΡ‚ ΠΎΠΊΠΎΠ»ΠΎ 300 мс, Ρ‚ΠΎ для всСх ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ это ΡƒΠΆΠ΅ сСкунда, Π·Π°Ρ‚Ρ€Π°Ρ‡ΠΈΠ²Π°Π΅ΠΌΠΎΠ΅ врСмя Π»ΠΈΠ½Π΅ΠΉΠ½ΠΎ зависит ΠΎΡ‚ числа ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ. Но Ρ€Π°Π· ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ количСства Ρ€Π΅ΠΏΠΎ Π½Π΅ зависит Π΄Ρ€ΡƒΠ³ ΠΎΡ‚ Π΄Ρ€ΡƒΠ³Π°, процСссы ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π°ΡΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΡ‚ΡŒ. Для этого Π½ΡƒΠΆΠ½Π° Ρ€Π°Π±ΠΎΡ‚Π° с .map ΠΈ Promise.all:

async function fetchAllCounts(users) {
  const promises = users.map(async username => {
    const count = await fetchPublicReposCount(username);
    return count;
  });
  return Promise.all(promises);
}

Promise.all Π½Π° Π²Ρ…ΠΎΠ΄Π΅ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ массив промисов с Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ΠΌ промиса. ПослСдний послС Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ всСх промисов Π² массивС ΠΈΠ»ΠΈ ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ Ρ€Π΅Π΄ΠΆΠ΅ΠΊΡ‚Π΅ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ. ΠœΠΎΠΆΠ΅Ρ‚ ΡΠ»ΡƒΡ‡ΠΈΡ‚ΡŒΡΡ Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎ всС ΠΎΠ½ΠΈ Π½Π΅ запустятся ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ, β€” для Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ запуск, ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ p-map.

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

Async-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ становятся всС Π±ΠΎΠ»Π΅Π΅ Π²Π°ΠΆΠ½Ρ‹ΠΌΠΈ для Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ. Ну Π° для Π°Π΄Π°ΠΏΡ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ использования async-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ стоит Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Async Iterators. JavaScript-Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π΄ΠΎΠ»ΠΆΠ΅Π½ Ρ…ΠΎΡ€ΠΎΡˆΠΎ Ρ€Π°Π·Π±ΠΈΡ€Π°Ρ‚ΡŒΡΡ Π² этом.

Skillbox Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΠ΅Ρ‚:

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com