Антон Ларичев
Разберёмся, что даёт нам запись return await и когда она действительно нужна, а когда создаёт дополнительную сложность в коде. Я очень часто во время ревью встречаю такую конструкцию:
async function getUserById(id: number) {
//...
return await db.find(id);
}
Чуть выше в каком-нибудь контроллере мы вызываем эту функцию:
const user = await getUserById(1);
Давайте разберём когда нужно использовать такую запись с await
, а когда
async function getUserById(id: number) {
//...
return db.find(id);
}
Что происходит?
Когда мы делаем return await
мы с вами фактически создаём ещё один Promise. То есть цепочка становится длиннее на один Promise. Сначала будет resolve
получения пользователя, а затем уже resolve
функции getUserById
. В целом на производительность и потребление памяти это почти не влияет, но зачем создавать новый Promise, если мы можем вернуть его на верхний уровень. Мы же хотим оптимальный код 🙂.
На самом деле результат выполнения будет идентичен в обоих случаях.
Когда нужен return await?
Единственный случай, когда нам пригодится return await
- это обработка ошибок в самой функции. Давайте перепишем нашу функцию следующим образом:
async function getUserById(id: number) {
try {
//...
return db.find(id);
} catch(e) {
// Что-то залогировать или обработать
// !!! Сюда мы никогда не попадём
throw e;
}
}
В это случаем мы хотим обработать ошибку ещё на уровне функции получения пользователя. Но без добавления await
мы никогда не попадём в блок catch
, так как reject
будет происходить уже на уровне выше. Это происходит потому, что мы просто вернули Promise без ожидания результата. И там уже вверху обработчик должен поймать ошибку, которая возникнет у нас в this.db.find(id)
.
А вот в примере с return await
мы будем успешно попадать в блок обработки ошибки:
async function getUserById(id: number) {
try {
//...
return await db.find(id);
} catch(e) {
// Что-то залогировать или обработать
// Если ошибка, то мы сюда попадём
throw e;
}
}
Дальше в блоке обработки вы можете прокинуть вверх ошибку как указано в примере или вернуть какой-то дефолтный / нулевой результат на ваше усмотрение.
Итог
Я бы предложил придерживаться следующих правил:
- Если вам нужно обработать ошибку на том уровне, где происходит возврат Promise - смело используйте
return await
. - Если же нет, просто делайте
return
, чтобы не создавать дополнительных Promise.
Карта развития разработчика
Получите полную карту развития разработчика по всем направлениям: frontend, backend, devops, mobile
16.11.2024
await давно уже не создаёт дополнительный промис под капотом
Комментарии
1