aysnc函数错误处理

最近,搭配koa和mysql2 (sequelize)使用的时候,查询数据库,会要捕获错误,sequelize提供的模型操作方法,均是返回promise对象,我们可以用thencatch 这样的链式方法 来获取查询数据结果,捕获错误;但是koa 支持 aysnc/ await 语法,我们可以更简洁地操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
	// 查询用户信息
user = await Models.users.findOne({
where:{
username: userName,
password:mdPwd
}
})

// 创建用户信息
rs = await Models.users.build({
user_id:userId,
username:userName,
password:mdPwd
}).save()

try … catch

​ 在使用aync/await,我们可以像写同步代码一样来完成数据的增删该查,但是这种方式我们无法捕获数据操作过程中的错误信息。如果需要捕获错误,我们可以借助 try {} catch{}。 下面是我demo中的错误处理代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 查询用户信息
let {userName,userPwd} = ctx.request.body;
const mdPwd = md5(userPwd)
// console.log(userName,userPwd)
let user
try{
user = await Models.users.findOne({
where:{
username: userName,
password:mdPwd
}
})
}catch(err){
// 捕获错误
return ctx.body = {
status: "1",
msg: err.message
}
}

// 用户名和密码已存在
if(user){
return ctx.body = {
status: '22',
msg: '用户名和密码已存在'
}
}
let userId = (Math.floor(Math.random() * 100000) + 100000000);
let rs;
// 写入用户信息,错误捕获
try{
rs = await Models.users.build({
user_id:userId,
username:userName,
password:mdPwd
}).save()
}catch(error){
return ctx.body = {
status: '1',
msg: err1.message,
result: ''
}
}

​ 上述 try {} catch{} 捕获错误的方法,也是繁琐,因为aysnc/await 处理的函数均会返回一个promise对象,

我们可以包装promise,使其返回统一的格式的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
 /**
* 包装promise, 使其返回统一的错误格式
* @param {Promise} promise
*/
function handlerAsyncError (promise) {
return promise.then(res => [null, res]).catch(err => [err])
}

// 简洁处理错误,减少try。。catch
const [err, res] = await handlerAsyncError(fetchUser(true))
if (err) {
console.error('touser err:', err)
}

async 顺序

​ 使用async的时候,代码执行的顺序很容易出错,比如我们要同时发起两个请求,可能会写出下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function fetchName () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('lujs')
}, 3000)
})
}

function fetchAvatar () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('https://avatars3.githubusercontent.com/u/16317354?s=88&v=4')
}, 4000)
})
}

async fetchUser () {
const name = await fetchName()
const avatar = await fetchAvatar()
return {
name,
avatar
}
}

​ 在上面的代码中,我们认为fetchName,fetchAvatar会并行执行,实际上并不会。fetchAvatar会等待fetchName执行完之后才开始请求。要并行请求的话需要像下面这样写:

1
2
3
4
5
6
7
8
async function fetchUserParallel () {
const namePromise = fetchName()
const avatarPromise = fetchAvatar()
return {
name: await namePromise,
avatar: await avatarPromise
}
}

使用Promise.all来并发请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function fetchList (id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`id is : ${id}`)
}, 5000)
})
}

async function getList () {
const ary = [1, 2, 3, 4]
const list = Promise.all(
ary.map(
(id) => fetchList(id)))
return await list
}
-------------本文结束感谢您的阅读-------------