#node.js #async-await #async.js
#node.js #async-await #async.js
Вопрос:
В настоящее время я использую async.js версия v2.3.0 с поддержкой асинхронной синхронизации ES2017.
Я пытаюсь понять, почему функция doSomething
, которая возвращает обещание, работает в IIEF, но doSomething2
не соблюдается. Это потому doSoomething2
, что это асинхронная функция, но она точно не выполняет «асинхронный» код? Я чувствую, что здесь что-то упускаю.
function promiseTimeOut() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(20);
}, 1000);
})
}
function doSomething() {
return new Promise((resolve, reject) => {
async.retry({
times: 5,
interval:(retryCount)=>{ return 50 * Math.pow(2, retryCount); }
}, async () => {
return await promiseTimeOut();
}, (err, result) => {
resolve(result);
});
})
}
async function doSomething2() {
async.retry({
times: 5,
interval:(retryCount)=>{ return 50 * Math.pow(2, retryCount); }
}, async () => {
return await promiseTimeOut();
}, (err, result) => {
return resu<
});
}
// main function
(async () => {
async.series([
(callback) => {
callback(null, 1);
},
async () => {
return await doSomething();
},
async () => {
// doesn't get waited on, returns undefined right away
return await doSomething2();
}
], (err, result) => {
// result: 1, 20, undefined
console.log(result);
});
})()
Ответ №1:
Вы пишете async.retry в стиле обратного вызова, чтобы он не ждал завершения. Попытайтесь console.log(result)
, вы могли бы увидеть
[ 1, 20, undefined ]
20
Посмотрите в документе retry
, как и в другом методе, в нем указано, что
Возвращает: обещание, если обратный вызов не предоставлен
Поэтому вам просто нужно немедленно вернуться, не предоставляя никакого обратного вызова
async function doSomething2() {
return async.retry(
{
times: 5,
interval: (retryCount) => {
return 50 * Math.pow(2, retryCount)
},
},
async () => {
return await promiseTimeOut()
}
)
}
Комментарии:
1. Это хороший момент. Async.js версия v2.3.0 по-прежнему поддерживает только обратные вызовы, поэтому я подозреваю, что мне придется обернуть это в обещание, чтобы заставить его работать. Однако в Async.js v3 , обещание будет возвращено, если обратный звонок не будет дан. Спасибо.
Ответ №2:
Async.js выполняет декомпиляцию вашего кода, чтобы адаптировать его поведение в зависимости от того, используете ли вы асинхронную функцию (которая возвращает обещания) или функции на основе обратного вызова. Вот почему вы можете видеть другое поведение, это просто зависит от простого факта наличия или отсутствия ключевого слова «async» перед вашей функцией (даже если поведение должно быть одинаковым).
Честно говоря, это не очень хорошая идея. Async.js неплох в том, что делает is, но явно представляет собой библиотеку, которая была создана для упрощения использования обратных вызовов и которая позже была обновлена, чтобы попытаться работать с promises. К сожалению, такое поведение автоматической магии, основанное на декомпиляции, может и будет вызывать проблемы. В качестве примера это может заставить код вести себя совершенно по-разному в зависимости от того, используете ли вы прекомпилятор, такой как Babel, или нет.
Недавно я опубликовал библиотеку, которая является альтернативой async.js и это было сделано именно для того, чтобы использовать только Promises (и async / await), создавая таким образом полностью согласованную библиотеку для работы с этими новыми инструментами.
Результат называется modern-async и находится здесь: https://nicolas-van.github.io/modern-async /