Оригинальная ссылка:Better error handling with async/await, Собио Дарлингтон
Эта статья знакомит с использованиемasync/awaitсинтаксис, лучший способ обработки ошибок. Перед этим вам также нужно понять, как работают промисы.
От ада обратных вызовов к обещаниям
Из-за вложенности функций обратного вызова,ад обратного звонкаЗаставляет ваш код течь вправо, а не вертикально вниз.
Для того, чтобы отразить функцию обратного вызова более интуитивно, вот пример.
Профиль пользователя, случай 1
// Code that reads from left to right
// instead of top to bottom
let user;
let friendsOfUser;
getUser(userId, function(data) {
user = data;
getFriendsOfUser(userId, function(friends) {
friendsOfUser = friends;
getUsersPosts(userId, function(posts) {
showUserProfilePage(user, friendsOfUser, posts, function() {
// Do something here
});
});
});
});
Promise
Промисы — это языковая функция, представленная в ES2015 (широко известная как ES6), чтобы лучше обрабатывать асинхронные операции и избегать ада обратных вызовов.
В следующем примере используется Promise.thenchain для решения проблемы ада обратного вызова.
Профиль пользователя, случай 2
// A solution with promises
let user;
let friendsOfUser;
getUser().then(data => {
user = data;
return getFriendsOfUser(userId);
}).then(friends => {
friendsOfUser = friends;
return getUsersPosts(userId);
}).then(posts => {
showUserProfilePage(user, friendsOfUser, posts);
}).catch(e => console.log(e));
Обещания обрабатываются более чистым и читабельным способом.
async/await Promise
async/await— это специальный синтаксис для более лаконичной обработки промисов.
существуетfuntionдобавить передasyncКлючевое слово преобразует функцию в обещание.
Возвращаемое значение всех асинхронных функций — обещание.
пример
// Arithmetic addition function
async function add(a, b) {
return a + b;
}
// Usage:
add(1, 3).then(result => console.log(result));
// Prints: 4
использоватьasync/await, чтобы вариант профиля пользователя 2 выглядел лучше.
Профиль пользователя, случай 3
async function userProfile() {
let user = await getUser();
let friendsOfUser = await getFriendsOfUser(userId);
let posts = await getUsersPosts(userId);
showUserProfilePage(user, friendsOfUser, posts);
}
так далее! Существует проблема
В «Случае профиля пользователя 3», если обещание отклоняется, оно выдаетUnhandled promise rejectionаномальный.
Ни в одном коде, написанном до этого, не учитывался отказ от Promise. Необработанные промисы отказа раньше молча терпели неудачу, что могло превратить отладку в кошмар.
Но теперь Promise отклоняется с ошибкой.
-
Ошибка, выданная Google Chrome:
VM664:1 Uncaught (in promise) Error -
Ошибка, выдаваемая узлом, выглядит так:
(node:4796) UnhandledPromiseRejectionWarning: Unhandled promise rejection (r ejection id: 1): Error: spawn cmd ENOENT
[1] (node:4796) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Ни одно промис не должно остаться незамеченным (каждое промис использует
.catchобработка).- Javascript
Обратите внимание, что в «Случае профиля пользователя 2».catchметод. если не написано.catchblock, JavaScript выдаст, когда Promise отклонитUnhandled promise rejectionошибка.
Легче решить проблему в User Profile Case 3. просто используйтеtry...catchпод блок-упаковкойawaitпредложения, которых следует избегатьUnhandled promise rejectionнеправильно.
Профиль пользователя, случай 4
async function userProfile() {
try {
let user = await getUser();
let friendsOfUser = await getFriendsOfUser(userId);
let posts = await getUsersPosts(userId);
showUserProfilePage(user, friendsOfUser, posts);
} catch(e) {
console.log(e);
}
}
Проблема решена!
Но может ли обработка ошибок быть более элегантной?
Как узнать, из какого асинхронного запроса возникла ошибка?
Может использоваться в асинхронных запросах.catchспособ обработки ошибок.
Профиль пользователя, случай 5
let user = await getUser().catch(e => console.log('Error: ', e.message));
let friendsOfUser = await getFriendsOfUser(userId).catch(e => console.log('Error: ', e.message));
let posts = await getUsersPosts(userId).catch(e => console.log('Error: ', e.message));
showUserProfilePage(user, friendsOfUser, posts);
Приведенное выше решение будет обрабатывать одну ошибку из запроса, но будет смешивать шаблоны. Должен быть более чистый способ использованияasync/awaitбез использования.catchметод (ну, вы можете сделать это, если вы не возражаете).
Мое лучшее решение для обработки ошибок async/await
Случай с профилем пользователя 6
/**
* @description ### Returns Go / Lua like responses(data, err)
* when used with await
*
* - Example response [ data, undefined ]
* - Example response [ undefined, Error ]
*
*
* When used with Promise.all([req1, req2, req3])
* - Example response [ [data1, data2, data3], undefined ]
* - Example response [ undefined, Error ]
*
*
* When used with Promise.race([req1, req2, req3])
* - Example response [ data, undefined ]
* - Example response [ undefined, Error ]
*
* @param {Promise} promise
* @returns {Promise} [ data, undefined ]
* @returns {Promise} [ undefined, Error ]
*/
const handle = (promise) => {
return promise
.then(data => ([data, undefined]))
.catch(error => Promise.resolve([undefined, error]));
}
async function userProfile() {
let [user, userErr] = await handle(getUser());
if(userErr) throw new Error('Could not fetch user details');
let [friendsOfUser, friendErr] = await handle(
getFriendsOfUser(userId)
);
if(friendErr) throw new Error('Could not fetch user\'s friends');
let [posts, postErr] = await handle(getUsersPosts(userId));
if(postErr) throw new Error('Could not fetch user\'s posts');
showUserProfilePage(user, friendsOfUser, posts);
}
Здесь используется функция полезностиhandle, чтобы избежатьUnhandled promise rejectionОтчеты об ошибках и детальная обработка ошибок.
объяснять
handleФункция принимает объект Promise в качестве параметра и всегда разрешает его, заканчивая[data|undefined, Error|undefined]возвращает результат в виде .
- Если Обещание разрешается,
handleвозврат функции[data, undefined]; - Если Обещание отвергается,
handleвозврат функции[undefined, Error].
похожие решения
В заключение
async/awaitСинтаксис удобен, но вам все равно придется иметь дело с выброшенными ошибками в асинхронных функциях.
Трудно справиться, если вы не реализуете пользовательские классы ошибокPromise.thenв цепи.catchОбработка ошибок.
использоватьhandleфункции полезности, мы можем избежатьUnhandled promise rejectionОтчеты об ошибках и детальная обработка ошибок.
(Конец текста)
коммерческое время(длительный эффект)
Моя хорошая знакомая владеет питомником, и я здесь, чтобы помочь ей распространить информацию. Теперь все кошки в питомникекукла кошка. Если вы также любите кошек и нуждаетесь в этом, вы можете также отсканировать ее [Xianyu] QR-код. Неважно, если вы не купите его, просто взгляните.
(над)