Асинхронность. ПродолжениеРеализуем Promisemedium

Реализуем async/await

Класс Promise появился в стандарте ES2015. Синтаксис async-await добавили в ES2017. Но на протяжении двух лет те, кто хотел писать «асинхронно в синхронном стиле» могли имитировать поведение async-await с помощью генераторов.

Наша задача — реализовать функцию runner, с помощью которой можно будет писать асинхронный код, используя ключевое слово yield вместо ключевого слова await.

Пример

Допустим, мы хотим сложить два числа, а результат возвести в куб, и для этого у нас есть две асинхронные функции. Такой алгоритм можно реализовать, используя async/await.

const sum = (a, b) => new Promise(r => setTimeout(r, 200, a + b)); const cube = num => new Promise(r => setTimeout(r, 300, num ** 3)); async function foo() { const res1 = await sum(1, 2); const res2 = await cube(res1); return res2; } foo(1, 2).then(console.log); // 27

Предположим, что у нас нет await, а мы не хотим строить цепочки then. Тогда функцию foo можно реализовать как функцию-генератор. После ключевого слова yield можно писать написать промис, разрешения которого мы будем дожидаться.

function* fooGen() { const res1 = yield sum(1, 2); const res2 = yield cube(res1); return res2; }

Естественно, если мы ее запустим, никакого результата мы не увидим.

Задача заключается в том, чтобы написать функцию runner, которая принимает подобные функции-генераторы, запускает асинхронный код и возвращает промис с результатом функции-генератора.

runner(fooGen).then(console.log); // 27