try/catch
,像这样
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fetch data is me')
}, 1000)
})
}
(async () => {
try {
const data = await fetchData()
console.log('data is ->', data)
} catch(err) {
console.log('err is ->', err)
}
})()
复制代码
这么看,感受却是没什么问题,若是是这样呢?有多个异步操做,须要对每一个异步返回的 error 错误状态进行不一样的处理,如下是示例代码typescript
const fetchDataA = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fetch data is A')
}, 1000)
})
}
const fetchDataB = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fetch data is B')
}, 1000)
})
}
const fetchDataC = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fetch data is C')
}, 1000)
})
}
(async () => {
try {
const dataA = await fetchDataA()
console.log('dataA is ->', dataA)
} catch(err) {
console.log('err is ->', err)
}
try {
const dataB = await fetchDataB()
console.log('dataB is ->', dataB)
} catch(err) {
console.log('err is ->', err)
}
try {
const dataC = await fetchDataC()
console.log('dataC is ->', dataC)
} catch(err) {
console.log('err is ->', err)
}
})()
复制代码
这样写代码里充斥着 try/catch
,有代码洁癖的你能忍受的了吗?这时可能会想到只用一个 try/catch
。promise
// ... 这里 fetch 函数省略
(async () => {
try {
const dataA = await fetchDataA()
console.log('dataA is ->', dataA)
const dataB = await fetchDataB()
console.log('dataB is ->', dataB)
const dataC = await fetchDataC()
console.log('dataC is ->', dataC)
} catch(err) {
console.log('err is ->', err)
// 难道要定义 err 类型,而后判断吗??
/** * if (err.type === 'dataA') { * console.log('dataA err is', err) * } * ...... * */
}
})()
复制代码
若是是这样写只会增长编码的复杂度,并且要多写代码,这个时候就应该想一想怎么优雅的解决,async/await
本质就是 promise
的语法糖,既然是 promise
那么就可使用 then
函数了异步
(async () => {
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fetch data is me')
}, 1000)
})
}
const data = await fetchData().then(data => data ).catch(err => err)
console.log(data)
})()
复制代码
在上面写法中,若是 fetchData 返回 resolve 正确结果时,data 是咱们要的结果,若是是 reject 了,发生错误了,那么 data 是错误结果,这显然是行不通的,再对其完善。async
(async () => {
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fetch data is me')
}, 1000)
})
}
const [err, data] = await fetchData().then(data => [null, data] ).catch(err => [err, null])
console.log('err', err)
console.log('data', data)
// err null
// data fetch data is me
})()
复制代码
这样是否是好不少了呢,可是问题又来了,不能每一个 await 都写这么长,写着也不方便也不优雅,再优化一下函数
(async () => {
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fetch data is me')
}, 1000)
})
}
// 抽离成公共方法
const awaitWrap = (promise) => {
return promise
.then(data => [null, data])
.catch(err => [err, null])
}
const [err, data] = await awaitWrap(fetchData())
console.log('err', err)
console.log('data', data)
// err null
// data fetch data is me
})()
复制代码
将对 await
处理的方法抽离成公共的方法,在使用 await
调用 awaitWrap
这样的方法是否是更优雅了呢。若是使用 typescript 实现大概是这个样子fetch
function awaitWrap<T, U = any>(promise: Promise<T>): Promise<[U | null, T | null]> {
return promise
.then<[null, T]>((data: T) => [null, data]) .catch<[U, null]>(err => [err, null]) } 复制代码
以上。优化