promise 的出现,提供了优雅的异步解决方式,可是,多个连续继发 promise 写法依然繁琐。react
let promise = new Promise(function(resolve, reject){
// ...
if(/* 异步任务执行成功 */) {
resolve(value)
} else {
reject(error)
}
})
promise.then(v => {}).catch(e => {})
复制代码
es6 以后又新增了 async 函数来优化异步写法,语义化更明确,写法更优雅,可是错误捕获比较麻烦,通常都得使用 try catch 来捕获错误,具体优势参考阮老师博客 async 函数es6
function promiseFunc = function(){
return new Promise(function(resolve, reject){
// ...
if(/* 异步任务执行成功 */) {
resolve(value)
} else {
reject(error)
}
})
}
async func(){
let res = await promiseFunc()
}
// 错误捕获
async func(){
try{
let res = await promiseFunc()
}catch(err){
alert(err)
}
}
复制代码
以下是工做中 react + mobx 项目中 action 的代码后端
class Actions {
@action
async deleteModel(params) {
try {
await this.post(apis.API_DEPLOY_DELETE, params)
this.getDeployList(this.store.searchParams)
} catch (e) {
message.error(e.message || '出错了!请稍后重试')
}
}
@action
async getDirChain(params) {
try {
let r = await this.post(apis.API_DEPLOY_DIR_CHAIN, params)
runInAction(() => {
this.store.dirChain = r
})
} catch (e) {
message.error(e.message || '出错了!请稍后重试')
}
}
}
复制代码
如上代码,两个 action 都是向后端异步请求数据, 每一个 action 函数中都用了 try catch 函数,这样重复写了几十个 action 函数api
必须干掉 try catchpromise
装饰器简洁方便,首先尝试, class 方法装饰器函数以下app
const tryCatch = msg => (target, name, descriptor) => {
const original = descriptor.value
if (typeof original === 'function') {
descriptor.value = async function(...args) {
try {
const result = await original.apply(this, args)
return result
} catch (e) {
message.error(e.message || msg || '出错了!请稍后重试')
}
}
}
return descriptor
}
复制代码
如上代码,封装 tryCatch 装饰器来对每一个 action 函数添加 try catch 错误捕获。异步
属性方法装饰器中async
咱们能够经过 descriptor.value 获取到被装饰的方法,在 try catch 中执行函数,捕获错误或者返回结果函数
为了灵活提示错误信息,装饰器参数 msg 用来传入自定义提示文本post
@tryCatch // @tryCatch('运行出错')
@action
async getDirChain(params) {
let r = await this.post(apis.API_DEPLOY_DIR_CHAIN, params)
runInAction(() => {
this.store.dirChain = r
})
}
复制代码
如上的写法是错误的,这种装饰器只能对
同步代码
产生做用,异步的是无效的,以前理解错误了
直接 async await 函数封装就好了,简单的问题想复杂了。。。
定义请求执行公共函数
/** * @param {string} method request method; ('get', 'post') * @param {string} api request url * @param {object} params payload * @memberof BaseActions */
request = async (method, api, params = {}) => {
const requestFunc = async () => {
let r = null
try {
r = await this[method](api, params)
} catch (e) {
message.error(e.message)
}
return r
}
return await requestFunc()
}
复制代码
原有包含 try catch 重复代码函数修改
@action
async getDirChain(params) {
let r = await this.request('get', apis.API_DEPLOY_DIR_CHAIN, params)
r && runInAction(() => this.store.dirChain = r)
}
复制代码
终于不用不停写重复代码了。。。