Переход с генераторов на Async/Await

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

Моя команда создала целое приложение со всеми модулями, состоящими из функций-генераторов, с одним вызовом модуля Co из основного js-файла.

Помимо обхода сотен функций генератора и изменения их с function*(...){ на async function(...){, как еще можно заставить генераторы работать с async/await?

Не имеет смысла, потому что yield*/generators и async/await очень похожи в том, как они обрабатывают поток, поэтому мне интересно, как они упустили наличие генераторов поддержки await.


person Glstunna    schedule 10.01.2017    source источник
comment
К вашему сведению, async/await не является частью ES7.   -  person Felix Kling    schedule 11.01.2017
comment
Кроме того, если вы хотите переписать большие части своего кода, рассмотрите возможность использования инструмента для этого, если это возможно: github. .com/facebook/jscodeshift (отказ от ответственности: это написал я)   -  person Felix Kling    schedule 11.01.2017
comment
В чем причина миграции?   -  person Bryan Chen    schedule 11.01.2017
comment
Я только что пришел к болезненному осознанию того, что функции генератора нельзя использовать с ожиданием. Только обещания или асинхронные функции. Не пробовал async/await, но любопытны шаблоны, в которых использовались генераторы, вызывающие проблемы. Можете ли вы включить пример функции генератора, которую нельзя использовать с async/await в вопросе?   -  person guest271314    schedule 11.01.2017
comment
Не имеет смысла, потому что yield*/generators и async/await очень похожи в том, как они обрабатывают поток - я не понимаю, что вы имеете в виду. Они могут быть похожи, но это не значит, что их можно объединить в нечто, объединяющее и то, и другое.   -  person Bergi    schedule 11.01.2017
comment
@Bergi - это действительно имеет смысл. Если обещание и асинхронная функция ожидаемы, то почему не генератор? В стране генераторов и обещания, и генераторы являются доходными.   -  person Glstunna    schedule 07.05.2017
comment
@Glstunna Потому что генераторы не были созданы для асинхронности. Только в co и других решениях, которые внедряют семантику async/await в функции-генераторы, промисы будут обрабатываться особым образом при получении.   -  person Bergi    schedule 07.05.2017


Ответы (3)


Вы должны просмотреть свою кодовую базу и изменить ее, да (конечно, вы можете написать/использовать инструмент, который сделает все за вас).

Но вы можете сделать это постепенно, если хотите: замените function* на async function, внутри него каждый yield на await и каждый yield* на await co(…), а затем измените каждый вызов прежней функции-генератора с co(…) на …().

person Bergi    schedule 10.01.2017

Нет необходимости переходить с одного на другое, потому что async функции и co библиотека могут мирно сосуществовать.

Функции async можно использовать внутри функций генератора co, это всего лишь функции, возвращающие обещания:

co.wrap(function* () {
    yield asyncFn(1);
})()
.catch(console.error);

Функции-генераторы можно использовать внутри async функций:

(async function () {
    await co(genFn(1));
    // for generator functions with no arguments, can also be 
    await co(genFn);
})()
.catch(console.error);

Помимо прохождения сотен функций генератора и изменения их с function*(...){ на async function(...){, как еще можно заставить генераторы работать с async/await?

Учитывая, что генераторы используются в приложении только в связке с co, их можно заменить в автоматическом режиме. Методы function* и * заменены аналогами async, yield и yield* заменены на await.

Прежде чем это можно будет сделать, необходимо провести некоторый предварительный рефакторинг. Из этого списка результатов следует использовать только промисы и генераторы. Параллельное выполнение (массивы и объекты) следует заменить на соответствующие Promise.all:

const results = yield [...];

to

const results = yield Promise.all([...]);
person Estus Flask    schedule 10.01.2017
comment
Откуда ко? - person delete; 18.06.2017
comment
@delete From github.com/tj/co . Я добавил ссылку на ответ. Угадайте, что это отвечает на вопрос, который вы только что опубликовали. - person Estus Flask; 18.06.2017

Если кому-то нужна дополнительная информация о переходе с co на async, вот подробная статья о миграции: https://medium.com/@nivekz/migrate-from-co-to-async-functions-4635d32d12bf

person user716468    schedule 30.07.2017