最近,搭配koa和mysql2 (sequelize)使用的时候,查询数据库,会要捕获错误,sequelize提供的模型操作方法,均是返回promise对象,我们可以用then... catch 这样的链式方法 来获取查询数据结果,捕获错误;但是koa 支持 aysnc/ await 语法,我们可以更简洁地操作。
// 查询用户信息
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中的错误处理代码
// 查询用户信息
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,使其返回统一的格式的代码
/**
* 包装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的时候,代码执行的顺序很容易出错,比如我们要同时发起两个请求,可能会写出下面的代码
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执行完之后才开始请求。要并行请求的话需要像下面这样写:
async function fetchUserParallel () {
const namePromise = fetchName()
const avatarPromise = fetchAvatar()
return {
name: await namePromise,
avatar: await avatarPromise
}
}
使用Promise.all来并发请求
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
}