Могу ли я использовать асинхронную функцию в качестве обратного вызова в node.js? - PullRequest
0 голосов
/ 05 ноября 2018

Могу ли я использовать асинхронную функцию в качестве обратного вызова? Примерно так:

await sequelize.transaction(async function (t1) {
    _.each(data,  async function (value)  {
        await DoWork(value);
    });
});
//Only after every "DoWork" is done?
doMoreWork();

Насколько я понимаю, нет никакой гарантии, что функция, вызывающая обратный вызов, будет ждать, пока обещание не будет решено, прежде чем продолжить. Правильно? Единственный способ убедиться, что произойдет, - это прочитать исходный код функции, в которую передается обратный вызов (например, исходный код «транзакции»)? Есть ли хороший способ переписать мой пример для правильной работы независимо от того, как реализована вызывающая функция?

1 Ответ

0 голосов
/ 05 ноября 2018

async функция может быть в качестве обратного вызова, но только если возвращаемое значение (обещание) используется каким-либо образом, который помогает поддерживать правильный поток управления. Примером является массив map callback.

Это тот же случай, что и эта проблема с forEach. Проблема в том, что transaction использует значение из async обратного вызова (обещание), но значение из each обратного вызова игнорируется.

Рецепт для выполнения обещаний последовательно с async равен for..of или другой оператор цикла:

await sequelize.transaction(async function (t1) {
    for (const value of data)
        await DoWork(value);
});

Рецепт для выполнения обещаний параллельно с async - Promise.all с map:

await sequelize.transaction(async function (t1) {
    await Promise.all(data.map(async (value) => {
        await DoWork(value);
    }));
});

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

...