задний план
У команды появился новый партнер, и мы обнаружили, что в спецификации кода нашей команды нам нужно датьasync await
Добавить кtry...catch
. Он был очень растерян: если их много (не сосредоточено), не нужно ли добавить много мест? Разве это не неэлегантно?
Почему обработка ошибок
JavaScript
Это однопоточный язык, если не добавленtry ...catch
, это вызовет прямую ошибку и не сможет продолжить выполнение. Конечно, это не означает, что вы должны использовать его в своем коде.try...catch
завернуть, использоватьtry...catch
означает, что вы знаете, что этот код местоположения может сообщить об ошибке, поэтому вы используетеtry...catch
Захватите обработку и дайте программе продолжить работу.
Я понимаю, что мы обычно делаемasync await
Когда он работает в асинхронном сценарии, этот сценарий не должен блокировать процесс, поэтому рекомендуется использоватьtry...catch
обработка.
async await для более элегантной обработки ошибок
Но, как сказал коллега,try...catch
Не очень элегантное поведение. Так что яGoogle
Через некоторое время я нашелHow to write async await without try-catch blocks in JavascriptБолее элегантный подход упоминается в этом посте и упакован в библиотеку -await-to-js. В этой библиотеке только одинfunction
, мы можем полностью применить эту функцию к нашему бизнесу следующим образом:
/**
* @param { Promise } promise
* @param { Object= } errorExt - Additional Information you can pass to the err object
* @return { Promise }
*/
export function to<T, U = Error> (
promise: Promise<T>,
errorExt?: object
): Promise<[U, undefined] | [null, T]> {
return promise
.then<[null, T]>((data: T) => [null, data]) // 执行成功,返回数组第一项为 null。第二个是结果。
.catch<[U, undefined]>((err: U) => {
if (errorExt) {
Object.assign(err, errorExt);
}
return [err, undefined]; // 执行失败,返回数组第一项为错误信息,第二项为 undefined
});
}
export default to;
Здесь должен быть пункт предварительных знаний:await ожидает возвращаемого значения обещания.
При нормальных обстоятельствах,await
За командой следуетPromise
объект, возвращает результат этого объекта. если неPromise
объект, он напрямую возвращает соответствующее значение.
Так что нам просто нужно использоватьPromise
характеристики соответственноpromise.then
а такжеpromise.catch
возвращает отдельный массив, в которомfulfilled
Когда первый элемент возвращаемого массиваnull
, второе - результат.rejected
, первый элемент возвращаемого массива — это сообщение об ошибке, а второй —undefined
. При использовании оцените, пуст ли первый элемент, вы можете узнать, есть ли ошибка, конкретное использование заключается в следующем:
import to from 'await-to-js';
// If you use CommonJS (i.e NodeJS environment), it should be:
// const to = require('await-to-js').default;
async function asyncTaskWithCb(cb) {
let err, user, savedTask, notification;
[ err, user ] = await to(UserModel.findById(1));
if(!user) return cb('No user found');
[ err, savedTask ] = await to(TaskModel({userId: user.id, name: 'Demo Task'}));
if(err) return cb('Error occurred while saving task');
if(user.notificationsEnabled) {
[ err ] = await to(NotificationService.sendNotification(user.id, 'Task Created'));
if(err) return cb('Error while sending notification');
}
if(savedTask.assignedUser.id !== user.id) {
[ err, notification ] = await to(NotificationService.sendNotification(savedTask.assignedUser.id, 'Task was created for you'));
if(err) return cb('Error while sending notification');
}
cb(null, savedTask);
}
резюме
async await
Добавление обработки ошибок в я лично считаю необходимым, но решение не толькоtry...catch
. использоватьasync await
а такжеPromise
С помощью этой функции мы можем более изящно обрабатывать ошибки асинхронного ожидания.