async/await
и обещания тесно связаны между собой. async
функции возвращают обещания, а ожидание является синтаксическим сахаром для ожидания разрешения обещания.
Единственным недостатком наличия комбинации обещаний и функций async
может быть удобочитаемость и удобство сопровождения кода, но вы, безусловно, можете использовать возвращаемое значение асинхронных функций в качестве обещаний, а также await
для обычных функций, которые возвращают обещание.
Выбор одного или другого в основном зависит от доступности (поддерживает ли ваш node.js / браузер async
?) И от ваших эстетических предпочтений, но от хорошего эмпирического правила (основанного на моих собственных предпочтениях во время написание) может быть:
Если вам нужно запустить асинхронный код последовательно: рассмотрите возможность использования async/await
:
return asyncFunction()
.then(result => f1(result))
.then(result2 => f2(result2));
против
const result = await asyncFunction();
const result2 = await f1(result);
return await f2(result2);
Если вам нужны вложенные обещания: используйте async/await
:
return asyncFunction()
.then(result => {
return f1(result)
.then(result2 => f2(result, result2);
})
против
const result = await asyncFunction();
const result2 = await f1(result);
return await f2(result, result2);
Если вам нужно запустить его параллельно: используйте обещания.
return Promise.all(arrayOfIDs.map(id => asyncFn(id)))
Предполагалось, что вы можете использовать await
в выражении для ожидания нескольких задач, например:
* обратите внимание, это все еще ожидает в последовательности слева направо, что нормально, если вы не ожидаете ошибок. В противном случае поведение отличается из-за сбой быстрого поведения из Promise.all()
const [r1, r2, r3] = [await task1, await task2, await task3];
(async function() {
function t1(t) {
console.time(`task ${t}`);
console.log(`start task ${t}`);
return new Promise((resolve, reject) => {
setTimeout(() => {
console.timeEnd(`task ${t}`);
resolve();
}, t);
})
}
console.log('Create Promises');
const task1 = t1(100);
const task2 = t1(200);
const task3 = t1(10);
console.log('Await for each task');
const [r1, r2, r3] = [await task1, await task2, await task3];
console.log('Done');
}())
Но, как и в случае Promise.all
, параллельные обещания должны быть правильно обработаны в случае ошибки. Вы можете прочитать больше об этом здесь .
Также будьте осторожны, чтобы не путать это с этим, так как на практике это будет запускать задачи последовательно. Задачи должны быть уже запущены .
let [r1, r2] = [await t1(100), await t2(200)];
function t1(t) {
console.time(`task ${t}`);
console.log(`start task ${t}`);
return new Promise((resolve, reject) => {
setTimeout(() => {
console.timeEnd(`task ${t}`);
resolve();
}, t);
})
}
console.log('Promise');
Promise.all([t1(100), t1(200), t1(10)]).then(async() => {
console.log('Await');
let [r1, r2, r3] = [await t1(100), await t1(200), await t1(10)]
});
Так что это не эквивалентно. Подробнее о разнице .
В конце концов, Promise.all
- более чистый подход, который лучше масштабируется для произвольного числа задач.