本文参加了由公众号@若川视野发起的每周源码共读活动,点击了解详情一起参与。
前言
按部就班,一步步来。
目标
下个项目熟练使用,减少错误处理代码。
开始
安装
- 空文件夹
test-await-to-js - Ctrl + Shift + ` ,选择 test-await-to-js
- type
npm i await-to-js --save
npm i await-to-js --save
文档
node_modules/await-to-js/dist/docs/index.html
Node 版本
if( Node 7.6 (or later) || an ES7 transpiler) can use.
Babel or ts for it.
- node version >= 7.6 ? Yes.
node -v
v14.5.0
用法
/**
* @param { Promise } promise
* @param { Object= } errorExt - Additional Information you can pass to the err object
* @return { Promise }
*/
function to(promise, errorExt) {
return promise
.then(function (data) {
return [null, data];
})
.catch(function (err) {
if (errorExt) {
Object.assign(err, errorExt);
}
return [err, undefined];
});
}
const UserModel = {
findById: (userId) => {
return new Promise((resolve, reject) => {
if (userId) {
const userObjet = {
id: userId,
notificationsEnabled: true,
};
return resolve(userObjet);
}
reject("Data is missing");
});
},
}; // 用户模块:根据id查询用户,用户存在则创建用户对象并启用通报服务,用户不存在则提示数据缺失。
const TaskModel = function ({ userId, name }) {
return new Promise((resolve, reject) => {
if (userId && name) {
const newTask = {
assignedUser: {
id: userId,
},
};
return resolve(newTask);
}
reject("Data is missing");
});
}; // 任务模块: 用户id和任务名都存在则新建任务并标记此任务分配给此用户,否则提示数据缺失。
const NotificationService = {
sendNotification: (userId, name) => {
return new Promise((resolve, reject) => {
if (userId && name) return resolve("Success");
reject("Data is missing");
});
},
}; // 通报服务:发送通知,执行成功,用户id和任务名都存在,则发送成功。
async function asyncTask(userId, cb) {
let err, user, savedTask, notification;
[err, user] = await to(UserModel.findById(userId));
if (!(user && user.id)) 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");
} // 异步任务之三:通报服务-发送通报,若用户通报功能启用,则执行此任务;用户id和任务名称都存在则发送成功,否则提示错误发生在通报发送过程中。
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");
} // 若用户id和任务被分配的用户id不一致,则重新执行异步任务之三:通报服务-发送通报。
cb(null, savedTask); //回调-新任务
}
asyncTask(1, (err, newTask) => {
console.log("new task created");
console.log(err);
console.log(newTask);
});
asyncTask(null, (err, newTask) => {
console.log("fail");
console.log(err);
console.log(newTask);
});
我的错误处理之路
第一阶段(使用 then 函数 catch 函数)
funcDemo().then((res)=>{
...
}).catch(err){
...
}
第二阶段(使用 async/await try...catch)
async function funcDemo(){
try {
await funcDemo()
...
}catch(err){
...
}
}
第三阶段(使用 async/await try...throw...catch)
async function funcDemo(){
try {
let res = await funcDemo()
if(...){
}else{
throw res
}
}catch(err){
}
}
第四阶段(使用 await-to-js)
async function funcDemo(){
let err,res
;[err,res] = await to(funcDemo())
...
}
- 以及今天使用 await-to-js 解决了过去产生的不易于理解维护的回调地狱的代码。
- 更接近作者的写法一步。
- 向未来前进了一步。
async function funcDemo(args,cb){
let err,res,res2
;[err,res] = await to(funcDemo())
...
;[err,res2]= await to(funcDemo2())
...
}
最后
-
感谢源码共读活动。
解决了工作中的不少问题,帮助我进步,感谢川哥,感谢无私奉献的人。
-
注重实践。
将学到的运用到工作中去。
参考链接
【若川视野 x 源码共读】第 21 期 | await-to-js 如何优雅的捕获 await 的错误
How to write async await without try-catch blocks in Javascript 官方文章