【JS】Promi.race()⽅法例⼦流程详解在理清Promi.all()中每个流程的时候实在是头⼤,理了半天,做此记录以便回顾
promi部分源码如下,只摘取⽤到的部分
八字成语大全100个function Promi(excutor){
const lf =this
lf.status ='pending'//给promi对象添加status属性,初始值为pending
lf.data =undefined//给promi对象指定data属性,⽤于储存结果数据
lf.callbacks =[]//每个元素的结构:{ onResolved() {} , onRejected() {} }
洱海介绍function resolve(value){
//如果当前状态不是pending,直接结束
if(lf.status !=='pending'){
return
}
//将状态改为resolved
lf.status ='resolved'
//保存value数据
lf.data = value
//如果有待执⾏的callback函数,⽴即异步执⾏onResolved
if(lf.callbacks.length >0){
tTimeout(()=>{//放⼊队列中执⾏所有成功的回调
lf.callbacks.forEach(callbacksObj =>{
});
});
}
}
function reject(reason){
//如果当前状态不是pending,直接结束
if(lf.status !=='pending'){
return
}
//将状态改为rejected
lf.status ='rejected'
//保存value数据
lf.data = reason
//如果有待执⾏的callback函数,⽴即异步执⾏onRejected
if(lf.callbacks.length >0){
tTimeout(()=>{//放⼊队列中执⾏所有成功的回调
lf.callbacks.forEach(callbacksObj =>{
});
});
}
}
//⽴即同步执⾏excutor
try{
excutor(resolve, reject)
}catch(error){//如果执⾏器抛出异常,则失败
reject(error)
}
}
Promi.prototype.then=function(onResolved, onRejected){
const lf =this
return new Promi((resolve, reject)=>{
if(lf.status ==='pending'){
if(lf.status ==='pending'){
/
/假设当前状态时pending状态
qq空间网址//此时的下⼀⾏的this,是调⽤then⽅法的promi,
电脑d盘//因为这是处于新promi的excutor'中,
this.callbacks.push({
onResolved:function(){
try{
//判断返回的是什么
//返回的是promi
const result =onResolved(lf.data)
if(result instanceof Promi){
result.then(
value =>resolve(value),
reason =>reject(reason)
)
}el{
//返回的是值,多次循环最终都是值,再包装成promi向上传递
//有点类似递归
resolve(result)
}
}catch(error){
reject(error)
}
},
onRejected:function(){
try{
//判断返回的是什么
//返回的是promi
const result =onRejected(lf.data)
if(result instanceof Promi){
result.then(
value =>resolve(value),
reason =>reject(reason)
)
}el{
//返回的是值,多次循环最终都是值,再包装成promi向上传递
//有点类似递归
resolve(result)
}
}catch(error){
reject(error)
}
}
})
}
}
/*
Promi函数对象的race()⽅法
返回⼀个promi,其结果由第⼀个完成的promi的状态
spank文章*/
Promi.race=function(promis){
return new Promi((resolve, reject)=>{
for(let i =0; i < promis.length; i++){
promis[i].then(v =>{
resolve(v)
}, r =>{
reject(r)
})
}
})
}
⽤作测试例⼦代码如下,promi结果均异步输出,excutor⽤ttimeout
let p1 =new Promi((resolve, reject)=>{
tTimeout(()=>{
resolve('1')
},1000);
})
let p2 =new Promi((resolve, reject)=>{
// resolve('2')
tTimeout(()=>{
resolve('2')
},1000);
初次遇见你
})
let p3 =new Promi((resolve, reject)=>{
// resolve('3')
tTimeout(()=>{
resolve('3')
},1000);
})
p1.aaa='我是标志'
let result1 = Promi.race([p1,p2, p3])
console.log(result1);
具体流程⽂字如下:
1.
⾸先p1,p2,p3三个实例对象被创建,但是其中的excutor没有执⾏,暂时进⼊异步队列等待同步任务完成;2.
进⼊Promi.race内部:
⾸先会创建⼀个新的Promi,为了⽅便叙述,
命名为newP,该对象即是测试html中的result,最后输出的内容
Promi.race=function(promis){
return new Promi((resolve, reject)=>{
for(let i =0; i < promis.length; i++){
promis[i].then(v =>{
语法知识
resolve(v)
}, r =>{
reject(r)
})
}
})
}
3.
大婶儿
进⼊构造newP对象的构造函数代码中,
此时newP的状态为pending,data为undefined
然后进⼊newP的excutor,即进⼊for循环
4.
会进⼊promis数组中第⼀个promi的then⽅法,循环后续都是⼀样的,只描述第⼀个循环的流程即可,
进⼊后会先构造⼀个新的Promi对象,记为insideP,进⼊构造函数内部的代码后,
insideP状态为pending,data为undefined
然后进⼊excutor,即下图⾥⾯,进⾏if判断
因为p1p2p3都处于pending,(此时的循环针对p1)所以会push⼀个对象{onResolved, onRejected}给p1的callbacks数组
5.
结束第⼀个循环,后续循环同理,直⾄同步代码全部完成,此时控制台打印了result但是newP的状态
是pending,(后续会⾃动改变)
此时异步队列开始运⾏,p1p2p3依次运⾏,
此时各个对象状态如下,全是pending
6.
p1的excutor⾥⾯的resolve(1)开始运⾏
⾸先改变p1pending为resolved,data为1,
因为callbacks数组在第4步被push进了⼀个对象,所以length不为0,
此时由与ttimeout,所以会将其放⼊异步队列,然后进⼊p2的resolve(2),同理p3的resolve(3)分别改变p2和p3的pending和data,但是不进⼊下⼀步操作,因为是异步的