前言
前一篇文章梳理了promise的基础聊聊promise系列(基础)
这篇文章将从容易出现错误的几种用法出发,得出如何去正确的用promise。
如何避免promise的回调地狱
想必大家在项目中会见过这样的写法。
const p1 = new promise((resolve, reject) => {
resolve(true);
})
p1.then((res) => {
if(res) {
const p2 = new promise((resolve, reject) => {
resolve(true);
})
p2.then((res) => {
const p3 = new promise((resolve, reject) => {
resolve(true);
})
})
}
})
这个写法写出了回调地狱的感觉。那如何优化他呢!!
const p1 = new promise((resolve, reject) => {
resolve(true);
})
const p2 = new promise((resolve, reject) => {
resolve(true);
})
const p3 = new promise((resolve, reject) => {
resolve(true);
})
p1.then((res) => {
if(res) {
return p2
}
}).then((res) => {
if(res) {
return p3
}
})
用这种链式调用的方式还是十分的优雅的。
catch() 与 then(null, ...) 并非完全等价
举个等价的例子:
Promise.reject('error').catch((res) => {
console.log(res);
})
Promise.reject('error').then(null, (res) => {
console.log(res);
})
catch
是用then(null, ...)
来实现的,但是在某些条件下,并不是等价的,比如以下例子:
const p1 = new Promise((resolve, reject) => {
if(/*正确的条件*/) {
resolve('success');
} else {
reject('false');
}
});
//用法一:
p1.then((res) => {
console.log(res);
throw new Error('我在then出错了');
}, (res) => {
console.log(res);
});
//用法二:
p1.then((res) => {
console.log(res);
throw new Error('我在then出错了');
}).catch((res) => {
console.log(res);
})
上述例子的区别就在与,catch可以捕捉then中发生的错误,但是then的第二个回调函数捕捉不了第一个参数中的报错。
输出的结果:
避免promise穿透问题
什么是promise穿透问题呢?举个例子:
Promise.resolve('foo').then(Promise.resolve('bar')).then(function (result) {
console.log(result);
});
这个鬼东西会输出啥??
斟酌良久,你可能回答bar,那你就错了,实际输出的是foo。
因为then
中希望获得的是一个函数。而当你传入一个promise
的时候,相当于then(null)
,无论你添加多少个then(null)
,promise都会穿透到下一个。
当然,对于上述例子,你可能希望的是这样做:
Promise.resolve('foo').then(() => {
return Promise.resolve('bar');
}).then(function (result) {
console.log(result);
});
切记,一定要往then里面传入函数
几种不同的写法带来的后果
接下来,我们通过一个例子,来看一下不同写法带来的后果。
const func = function(last, num) {
return new Promise((resolve, reject)=>{
console.log(last, num);
resolve(num);
});
};
// 写法一
Promise.resolve()
.then((last)=>{return func(last, 1);})
.then((last)=>{return func(last, 2);})
.then((last)=>{return func(last, 3);});
// 写法二
Promise.resolve()
.then((last)=>{func(last, 1);})
.then((last)=>{func(last, 2);})
.then((last)=>{func(last, 3);});
// 写法三
Promise.resolve()
.then(func(undefined, 1))
.then(func(undefined, 2))
.then(func(undefined, 3));
// 写法四
func(undefined, 1).then(func(undefined, 2)).then(func(undefined, 3));
- 写法一
结果:
undefined 1
1 2
2 3
这是我们想要的结果,也是promise链式调用正确的写法。
- 写法二 结果:
undefined 1
undefined 2
undefined 3
虽然在then中执行了函数,但是并没有return有结果的promise给下一个then,所以后面的then永远是收不到结果值的。
- 写法三
结果:
undefined 1
undefined 2
undefined 3
这种写法是造成promise穿透引起的。then里面需要是一个函数,但是却传了一个promise进去。
- 写法四
结果:
undefined 1
undefined 2
undefined 3
和第三种也发一致,也是promise穿透,then里面需要是一个函数,但是却传了一个promise进去。