先看一段平时调用的promise的代码
new Promise((resolve,reject)=>{
console.log(123)
resolve('2')
}).then((res)=>{
console.log(res)
})
在上面代码代码中,可以看到构造函数返回了一个promise实例对象,然后实例对象在调用then函数,这就说明then函数是已经被调用起了
- 第一步,结合promise的源码来看
代码1
class Promise(){
construtor(excutor){
//其中的excutor必须是函数
if(typeof excutor !== function ){
throw new TypeError('excutor is not a function')
}
//定义属性
this.status = 'pending';
this.value = undefine;
this.resolveCallback = [];
this.rejectCallback = [];
let resolve(result){
if(this.status == 'pending'){
this.status = 'resolve';
this.value = result;
//为了这段代码是保证then函数后面被执行,所以添加了setTimeout这个宏观任务,因为then是微观任务,这个setTimeout是第二轮的宏观任务,then是第一轮的微观任务,这样是保证then里面的this.resolveCallback.push()代码能够被执行进去,才会有函数被执行
setTimeout(()=>{
this.resolveCallback.forEach((item)=>{
item(result)
})
})
}
}
let reject(reason){
if(this.status == 'pending'){
this.status = 'reject';
this.value = reason;
setTimeout(()=>{
this.rejectCallback.forEach((item)=>{item(reason)})
})
}
}
try{
excutor(resolve,reject)
}catch(err){
reject(err)
}
}
}
解释:在源码中,我们在promise传入了一个excutor的执行函数,在我们调用的代码resolve('2')之前的时候,status一直保持着pending的状态,then里面的函数(this.resolveCallback.push())已经执行,到代码resolve('2')时,excutour(resolve)调用,状态resolve被凝固,在构造函数里面的resolve方法遍历中,then方法的参数onFufilled函数被执行,恰好证明了promise的resolve成功调用起then的resolve的状态回调,reject也是同理。
- 第二步 then里面的调用
代码2
在代码1中,添加then方法
then(onFufilled,onRejected){
//验证传入的onFufilled和onRejected方法必须是函数
onFufilled = typeof onFufilled ==='Function' ? onFufilled : function(val){return val};
onRejected = typeof onRejected ==='Function' ? onRejected :function(val) {return val} ;
//返回一个promise才可以保证下面的then的方法的链式调用
return new Promise((resolve,reject)=>{
//this指向上一个promise对象,push进去的函数是在构造函数中的resolve方法中执行
this.resolveCallback.push((result)=>{
try{
let x = onFufilled(result)
//这里的resolve和reject是x这个实例对象的,如果x里面resolve的话就会调用then的成功回调的执行,如果x里面reject的话就会调用then的失败回调的执行
x instanceof Promise ? x.then(resolve,reject) :resolve(x);
}catch(e){
reject(e)
}
})
this.rejectCallback.push((result)=>{
try{
let x = onRejected(result)
x instanceof Promise ? x.then(resolve,reject) :resolve(x);
}catch(e){
reject(e)
}
})
})
}
解释:then方法,在我们平时调用的promise中,new Promise().then(),已经被调用起了。 在浏览器的执行中,分宏任务和微任务,结合代码1和代码2,分析下new Promise().then()的执行,new Promise是第一宏任务,then是第一微任务,先执行完宏任务,再执行微任务,这是执行的顺序,现在看一下Promise构造函数里面的代码,重点是resolve这个函数,里面有个setTimeout,这是第二个宏观任务,所以,当new Promise里面的代码执行完之后,但是此时的setTimeout没有被执行,此时浏览器已经去执行了then,所以,this.resolveCallback数组才有值,第一微任务执行完之后,才去执行第二宏任务,这个就是resolveCallback里面的函数的调用;
静态方法
第一个:Promise.resolve
Promise.resolve((value)=>{
return new Promise((resolve,reject)=>{
try{
value instanceof Promise ? value.then(resolve,reject) :resolve(value);
}catch(e){
reject(e)
}
})
})
第二个:Promise.reject
Promise.reject((value)=>{
return new Promise((resolve,reject)=>{
reject(value)
})
})
第三个:Promise.all
Promise.all((promises)=>{
//传入的参数promises是每个key值为promise对象的数组
return new Promise((resolve,reject)=>{
let count =0;
let promiseLength = promises.length;
let resolveValue = new Array(promiseLength);
for(let i=0;i<promiseLength;i++){
(function(i){
Promise.resolve(promises[i]).then((res)=>{
count++;
resolveValue[i] = res;
if(count === promiseLength){
return resolve(resolveValue)
}
},(err)=>{
return reject(err)
})
})(i)
}
})
})
解释:promise.all对一系列promise实例的触发,每个实例必须全部为resolve的时候,它才返回每个promise实例结果组成的数组。
原型方法
第一个:Promise.prototype.then
参照上面的代码2
第二个:Promise.prototype.catch
Promise.prototype.catch = ((onRejected)=>{
retrun this.then(null,onRejected)
})