Две асинхронные функции — add и mul
const add = (x, y) => Promise.resolve(x + y) const mul = (x, y) => Promise.resolve(x * y)
Чтобы проиллюстрировать различные асинхронные конструкции, мы напишем другую функцию, которая делает что-то эквивалентное:
const fn = (x, y, z) => console.log(mul(add(x, y), z))
Использование промисов
Код для этого довольно прост.
const foo = (x, y, z) => { add(x, y) .then((addResult) => mul(addResult, z)) .then((mulResult) => console.log(`${mulResult}`)) }
Использование генераторов
Использование генераторов позволяет нам писать код, который выглядит линейно. Только нам придется оборачивать генератор в сопрограмму.
const bar = coroutine(function* (x, y, z) { let addResult = yield add(x, y) let mulResult = yield mul(addResult, z) console.log(`${mulResult}`) })
Приведенная ниже функция сопрограммы принимает обещание, полученное от генератора, и передает его обратно генератору с помощью метода next его итератора. Так происходит до тех пор, пока в генераторе не останется операторов yield.
const coroutine = generator => function() { let it = generator.apply(null, arguments) let next = it.next() let coInterval = setInterval(() => { next.done ? clearInterval(coInterval) : next.value.then(result => next = it.next(result)) }) }
Использование асинхронного/ожидания
Структура кода аналогична синхронно написанной функции (так же, как генератор/выход), но без необходимости оборачивать нашу функцию в сопрограмму (как в случае с генераторами).
const baz = async (x, y, z) => { let addResult = await add(x, y) let mulResult = await mul(addResult, z) console.log(`${mulResult}`); }