这个也是紧接着 Symbol、原型链的第三篇有关JavaScript基础的相关内容,这个也是比较重要的内容,我们这篇文章的主题将会紧紧围绕下面这幅图展开:
当然,如果想看完整的总结,请直接滑到文章的最后。
它其实就是一个构造函数,通过 new 这样的构造函数来创建一个promise实例,最后使用promise相关的API,让你的代码能够在未来的可预测的某个时刻去执行。
它提供了一种让代码异步运行的全新解决方案。
处理promise相关的错误时,大致分为3类,分别如下:
这一块大家还是要了解它的明细的,因为我们使用promise,80%的场景下都是并发处理,错误处理不恰当,就会导致意想不到的bug发生。
这一块的API较多,我大致列举了一下思维导图,如下:
参数:由promise实例组成的数组。
数组里各项的执行顺序:并发执行。
返回:如果有一个实例失败,那么就返回失败的信息;如果全部都成功了,那么就会返回一个数组,数组里包含了每个promise实例成功的信息。
运行流程:
1、如果各promise实例的状态都是resolve,那么就会先执行各自实例的 then函数,然后再执行 Promise.all.then。
2、如果promise实例中,有一个状态被reject了,那么就会触发Promise.all.catch,其余还没执行完的promise实例将继续执行,只不过无论如何都不会再触发Promise.all.catch 或者 Promise.all.then了。
我们实际code一下:
let p1 = function(){
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve(1);
}, 1000);
});
}
let p2 = function(){
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve(2);
}, 2000);
}).then(res => {
console.log('p2的then实例:', res);
});
}
Promise.all([p1(), p2()]).then(res => {
console.log('最终收到的响应:', res);
})
上面的代码运行以后,我们的控制台会输出下面的信息:
/***
p2的then实例: 2
最终收到的响应: [ 1, undefined ]
*/
为什么数组第二项是一个undefined呢?最开始我们说过,promise里所有的API都会返回一个新的Promise实例,我们给p2注册的then方法里并没有明确返回值,所以输出是undefined,符合预期。
参数:由promise实例组成的数组。
数组里各项的执行顺序:并发执行。
返回:返回实例里状态改变最快的实例结果。
运行流程:
1、多个promise实例,看谁的状态最先发生改变,那么 promise.race.then 或者 promsie.race.catch 就返回 最快的resolve或者reject。
2、如果有没跑完的promise实例就接着跑,只是不会再触发 promise.race.then 或者 promise.race.catch。
我们来coding一下:
let p1 = function(){
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve(1);
}, 1000);
});
}
let p2 = function(){
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve(2);
}, 2000);
}).then(res => {
console.log('p2的then实例:', res);
return res;
});
}
Promise.race([p1(), p2()]).then(res => {
console.log('最终收到的响应:', res);
})
运行一下代码,结果如下:
/***
最终收到的响应: 1
p2的then实例: 2
*/
参数:由promise实例组成的数组。
数组里各项的执行顺序:并发执行。
返回:将各实例的结果按顺序组成一个数组并返回。
运行流程:
1、会等待所有的promise实例状态都发生变化,才会去触发 Promise.allSettled.then。
2、返回的是一个结果数组。
每一项都包含status状态(fulfilled、rejected)字段来标识promise实例是resolve还是被reject。
我们再把这个coding一下:
let p1 = function(){
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve(1);
}, 1000);
});
}
let p2 = function(){
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve(2);
}, 2000);
}).then(res => {
console.log('p2的then实例:', res);
return res;
});
}
Promise.allSettled([p1(), p2()]).then(res => {
console.log('最终收到的响应:', res);
})
看下控制台的输出结果:
/***
p2的then实例: 2
最终收到的响应: [
{ status: 'fulfilled', value: 1 },
{ status: 'fulfilled', value: 2 }
]
*/
参数:promise实例组成的数组。
各实例的执行顺序:并发执行。
返回:哪个promise的实例状态最先被置为fulfilled,就返回它。
这个就不coding了,留给大家自己去实践吧。
下面列举了一些比较常见的应用,如下:
这个主要考察了Promise.all、Promise.allSettled 的应用。当然在实际工作中,allSettled的使用频率较高,这里就不细说了。
相信大家都遇到过这样的题目:
1s红灯,下一秒绿灯,下一秒黄灯,再下一秒红灯,如此往复...
这种重复执行的内容,采用递归一定是不行的
。因为每次调用一个函数,都会为它创建执行上下文并压入栈中,栈的容量是有限的,因为这道题不存在pop场景,所以使用递归,一定会爆栈。
定时器setInterval + 全局变量
就是一个很好的实现手段,但是不知道为啥,这种题目会跟promise关联上,想不懂。
我写文章有时候确实是这样,我只写我认为有意义的东西,但是我又来者不拒,所以大家可以把这道题的意义写在评论区里,没准看到评论,我的思路被打开了,才会去重视这道题。
想要实现这个内容,首先我们要想想这个API的特点以及实现的难点:
有了上述的分析,我们就可以实现all这个API:
let customAll = (instanceArr) => {
let failReason = null;
let result = [];
return new Promise((fulfilled, rejected) => {
instanceArr.forEach(item => {
item.then(succcess => {
result.push(succcess);
if (result.length === instanceArr.length){
// 说明全部都执行成功啦,直接返回
return fulfilled(result);
}
})
.catch(err => {
if (failReason === null){
// 返回第一个失败的实例
failReason = err;
return rejected(failReason);
}
})
});
});
}
这个的实现思路跟all差不多,主要修改2个点:
有了上面的分析,不难写出这个方法的实现:
let customAllSettled = (instanceArr) => {
let failReason = null;
let result = [];
return new Promise((fulfilled, rejected) => {
instanceArr.forEach(item => {
item.then(succcess => {
result.push({
status: 'fulfilled',
value: succcess
});
if (result.length === instanceArr.length){
// 说明全部都执行成功啦,直接返回
return fulfilled(result);
}
}).catch(err => {
result.push({
status: 'rejected',
value: err
});
if (result.length === instanceArr.length){
fulfilled(result);
}
});
});
});
}
这个API的实现思路跟之前的都差不错,它是赛马机制,所以我们需要一个全局变量,这个全局变量用来判定谁的状态是第一个发生改变的。
let customRace = (instanceArr) => {
let isFirst = null;
return new Promise((fulfilled, rejected) => {
instanceArr.forEach(item => {
item.then(succcess => {
if (isFirst === null){
isFirst = true;
return fulfilled(succcess);
}
}).catch(err => {
if (isFirst === null){
isFirst = true;
return rejected(err);
}
});
});
});
}
又到了该说再见的时候了,希望这篇文章的讲解可以对你有帮助,噢对了,我最近搭建了一个交流群,里面可以自由探讨技术,如果你感兴趣,欢迎添加我的微信:18845097791,我拉你入群。那么我们下期再见啦,拜拜~~