使用场景: 在使用promise封装通用函数时(例如封装请求函数) 通常会对promise的失败情况做统一处理;为了某些时候,需要单独对失败做处理,就需要将失败抛出;但不需要对失败单独处理的时,又因失败抛出没有绑定失败回调函数导致程序报错
注意使用场景,因对失败情况做统一处理,避免开发过程中 因失败情况导致一些错误难以排查
平时我们封装的api请求
// 封装请求
function request(config) {
return axios(config).then(res => {
// 请求状态码不等于200,算请求失败
if(res.code !== 200) return Promise.reject(res)
// 对请求数据做再次封装
return res
}).catch(err => {
// 对请求失败做处理
// 例如:提示用户请求失败,或者返回到上一页
return Promise.reject(err)
})
}
使用request
// 请求使用
request({
url: 'url'
}).then(res => {}) // 此时未绑定失败回调,在请求失败时程序会报错
此时请求失败控制台会有以下报错
你必须对请求失败做处理
request({
url: 'url'
}).then(res => {}).catch(() => {}) // 但在接口封装里对失败做了处理,这里我们不需要再次处理失败
对与以上使用遇到的问题,对promise进行了再次封装
/**
* 封装promise,解决无catch的promise异常,注意! 本身不具备promise的功能,成功和失败来自传入的promise实例
* @param {Promise} promise 接受一个promise实例
*/
class MyPromise {
promise
_onRejected
_onCatch
constructor(promise) {
this.promise = promise
this._onCatch = this.promise.catch(res => {
if(this._onRejected) {
return Promise.reject(res)
}
})
}
then(onFulfilled, onRejected) {
if(onFulfilled) return new MyPromise(this.promise.then(onFulfilled))
return this.catch(onRejected)
}
catch(onRejected) {
this._onRejected = onRejected
// 不破坏promise 链式调用的特性,但又保证异常时程序不报错
return new MyPromise(this._onCatch.catch(onRejected))
}
finally(onFinally) {
return new MyPromise(this.promise.finally(onFinally))
}
}
使用示例
// 使用不会对promise的本身使用产生影响,注意! 本身不具备promise的功能,成功和失败来自传入的promise
new MyPromise(
Promise.resolve('我是结果') // 这个promise 最后一次的catch也返回
).then(res => {
console.log(1);
return res
}).then(res => {
console.log(2);
return Promise.reject(res)
}).catch(err => {
console.log(3);
return Promise.reject(err)
}).catch(err => {
console.log(4);
return Promise.reject(err)
})
// 或者这样
new MyPromise(Promise.resolve('我是结果').then(res => {
console.log(1);
return res
}).then(res => {
console.log(2);
return Promise.reject(res)
}).catch(err => {
console.log(3);
return Promise.reject(err)
}).catch(err => {
console.log(4);
return Promise.reject(err)
}))
// 输出结果 1,2,3,4
使用 myPromise 重新封装请求
function request(config) {
return new MyPromise(axios(config).then(res => {
// 请求状态码不等于200,算请求失败
if(res.code !== 200) return Promise.reject(res)
// 对请求数据做再次封装
return res
}).catch(err => {
// 对请求失败做处理
// 例如:提示用户请求失败,或者返回到上一页
return Promise.reject(err)
}))
}
使用请求
request({
url: 'url'
}).then(res => {}) // 这里就不会报错了
request({
url: 'url'
}).then(res => {
}).catch(() => {
// 这里可以对失败再次做处理
})