Разница между "возвратом ждут обещания" и "возвращением обещания"
Учитывая примеры кода ниже, есть ли разница в поведении и, если да, то каковы эти различия?
return await promise
async function delay1Second() {
return (await delay(1000));
}
return promise
async function delay1Second() {
return delay(1000);
}
Как я понимаю, первый будет иметь обработку ошибок в функции async, и ошибки будут выходить из асинхронной функции Promise. Однако второй потребовал бы еще одного тика. Правильно ли это?
Этот фрагмент является просто общей функцией для возврата обещания для ссылки.
function delay(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
Ответы
Ответ 1
В большинстве случаев между return
и return await
нет заметной разницы. Обе версии delay1Second
имеют одно и то же наблюдаемое поведение (но в зависимости от реализации версия return await
может использовать немного больше памяти, поскольку может быть создан промежуточный объект Promise
).
Однако, как отметил @PitaJ, есть один случай, когда есть разница: если return
или return await
вложен в блок try
- catch
. Рассмотрим этот пример
async function rejectionWithReturnAwait () {
try {
return await Promise.reject(new Error())
} catch (e) {
return 'Saved!'
}
}
async function rejectionWithReturn () {
try {
return Promise.reject(new Error())
} catch (e) {
return 'Saved!'
}
}
В первой версии функция async ожидает отклоненное обещание перед возвратом его результата, что приводит к тому, что отказ отклоняется в исключение и предложение catch
должно быть достигнуто; функция, таким образом, вернет обещание, разрешающее строку "Сохранено!".
Однако вторая версия функции возвращает отклоненное обещание напрямую, не ожидая его в рамках функции async, что означает, что случай catch
не вызывается, а вызывающий получает отказ.
Ответ 2
Это трудный вопрос для ответа, потому что на практике это зависит от того, как ваш транспилер (возможно, babel
) действительно отображает async/await
. То, что ясно, независимо:
-
Обе реализации должны вести себя одинаково, хотя в первой реализации может быть меньше Promise
в цепочке.
-
Особенно если вы сбросите ненужный await
, вторая версия не потребует дополнительного кода от транспилятора, а первая сделает.
Таким образом, из производительности кода и перспективы отладки вторая версия предпочтительнее, хотя и очень незначительно, в то время как первая версия имеет небольшую удобочитаемость, поскольку она ясно указывает, что она возвращает обещание.