1.async函数中为什么需要捕获异常?
任何一个
await
语句后面的 Promise 对象变为reject
状态,那么整个async
函数都会中断执行。有时,我们希望即使前一个异步操作失败,也不要中断后面的异步操作。这时可以将第一个await
放在try...catch
结构里面,这样不管这个异步操作是否成功,第二个await
都会执行。
那么也意味着并不是所有的async函数中都需要使用trycatch。比如,有这样一个场景,项目中写了一个定时刷新列表的异步任务,如果刷新成功,则提示用户:数据已于XXX时间更新成功。此时,如果使用了try...catch,则会出现接口刷新失败,也会提示用户数据刷新成功。
js
enableLoopTask(){
if(this.timerId) clearInterval(this.timerId)
this.timerId = setInterval(()=>{
this.loadData()
const refreshTime = moment(Date.now()).format("YYYY-MM-DD HH:mm:ss")
this.$message.success(`当前列表数据已于${refreshTime}更新成功,请查看!`);
},1000 * 5)
},
// 点击查询时判断是否是当天,是当天 需要间隔30min刷新一次数据
searchQuery() {
this.queryParams = Object.assign({},this.formData)
this.loadData()
const isEnable = this.formData.businessDate === today
if(!isEnable) {
clearInterval(this.timerId)
return
}
this.enableLoopTask()
},
2.什么情况下需要处理异常
2.1多个异步请求串行
js
try {
// 获取列表list
const list = await getList(params)
// 获取单个详情
const info = await getListById(list[0]?.id)
} catch {}
2.2处理异步请求的 loading 状态
js
try {
this.loading = true
// 获取列表list
const list = await getList(params)
} finally {
this.loading = false
}
如果请求接口失败就想一直loading,那就另外处理了。因为await 命令后面的函数本身是一个promise,所以上面的也可以直接使用catch,如下:
js
this.loading = true
let res = await getList().catch(() => (this.loading = false))
if (!res) return
3.那怎么避免项目中大量的try-catch~呢?
js
/**
* @param { Promise } promiseFn
* @param { Object= } errorExt - Additional Information you can pass to the err object
* @return { Promise }
*/
function fetchAsyncTuple(promiseFn,errorExt){
return promiseFn.then(res=>{
return [res,null]
}).catch(error=>{
if(errorExt) {
const combineError = Object.assign({},error,errorExt)
return combineError
}
return [undefined,error]
})
}
优化后,业务中直接这样类似这样使用:
js
async getProjectInfoList(params) {
this.infoListLoading = true;
if (params === 1) {
this.paginationProps.page = 1;
}
const [data,error] =await fetchAsyncTuple(fetchProjectInfoList(this.queryParams))
if(!error){
this.paginationProps.total = data.data.page.totalCount;
this.tableData = data.data.page.list;
this.infoListLoading = false;
}
},
没优化前是这样的:
js
async getProjectInfoList(params) {
this.infoListLoading = true;
if (params === 1) {
this.paginationProps.page = 1;
}
try {
const res = await fetchProjectInfoList(this.queryParams);
this.paginationProps.total = res.data.page.totalCount;
this.tableData = res.data.page.list;
this.infoListLoading = false;
} catch (error) {
console.error("error---", error);
} finally {
this.infoListLoading = false;
}
},
或者这样是否也可以呢?
js
const fetchAsyncTuple = async (promiseCallback) => {
try {
const res = await promiseCallback
if (res) {
return [res, null]
}
} catch (error) {
return [null, error]
}
}