最近在掘金上刷面试题的时候不可或非的多次遇到了Promise的问题,于是通过万能的搜索引擎,研究一番之后终于对Promise的源码才有了一个初步的理解,希望小伙伴能在此得到一点收获
你真的懂 promise 的运行机制吗?
new 一个promise的时候需要传递一个执行器函数,立即执行
执行器函数只接受两个参数 resolve reject
Promise有三个状态 pedding fulfilled rejected
状态改变只能由pendding -> fulfilled 或者 pendding -> rejected
状态一经确定就无法改变
我们所了解的 then 链式调用
Promise 的 then 可以链式调用(返回一个promise对象)
可接收两个参数(可缺省),一个是成功的回调onFulfilled 一个是失败的回调onRejected
如果成功且有返回值,则如果返回值为Promise对象则等待promise执行完成
如果成功则走下一个Promise成功的回调否则就走失败的回调
如果返回值是其他类型则直接作为下一个then对应的成功或失败的回调(在成功的回调返回就走下一个then成功的回调,反之亦然)
源码解读
const PENDDING='pendding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'
function Promise(fn){
let self = this;
/**初始化状态*/
self.status=PENDDING;
/**保存成功回调函数*/
self.onFulfilledCallBack=[];
/**保存失败的回到数组*/
self.onRejectedCallBack=[];
/**执行成功回调 */
function resolve(value){
if(self.status===PENDDING){
self.status=FULFILLED;
self.value=value;
self.onFulfilledCallBack.forEach(fn=>fn(self.value))
}
}
/**失败回调*/
function reject(reason){
if(self.status===PENDDING){
self.status=REJECTED;
self.reason=reason;
self.onRejectedCallBack.forEach(fn=>fn(self.reason))
}
}
/**立即执行传入的函数,并加一层捕获异常 */
try {
fn(resolve,reject)
} catch (error) {
reject(error)
}
}
Promise.prototype.then=function(onFulfilled,onRejected){
/**确保用户在没有传入回调函数的时候将值往后传*/
onFulfilled = typeof onFulfilled=== "function"?onFulfilled:value=>value;
onRejected = typeof onRejected=== "function"?onRejected:reason=>{throw reason};
let self=this;
let promise2=new Promise(function(resolve,reject){
if(self.status===FULFILLED){
try {
/**因为Promise是属于微任务,所以在这里需要在外层包裹一个setTimeout
保证它处于异步队列(关于这个问题的具体原因可以百度一下js事件循环机制)
*/
setTimeout(()=>{
let x = onFulfilled(self.value);
resolvePromise(promise2,x,resolve,reject)
})
} catch (error) {
reject(error)
}
}else if(self.status===REJECTED){
try {
setTimeout(()=>{
let x = onRejected(self.reason);
resolvePromise(promise2,x,resolve,reject)
})
} catch (error) {
reject(error)
}
}else if(self.status===PENDDING){
/**
如果在调用then函数的时候promise状态还处于pendding状态
则将处理函数分别存入对应的成功或失败的处理函数数组中
*/
self.onFulfilledCallBack.push(()=>setTimeout(()=>{
try {
let x = onFulfilled(self.value);
resolvePromise(promise2,x,resolve,reject)
} catch (error) {
reject(error)
}
}))
self.onRejectedCallBack.push(()=>setTimeout(()=>{
try {
let x = onRejected(self.reason);
resolvePromise(promise2,x,resolve,reject)
} catch (error) {
reject(error)
}
}))
}
})
return promise2;
}
/**处理在then函数中返回值*/
function resolvePromise(promise2,x,resolve,reject){
/**确保只执行一次*/
let used;
/**如果出现传入的x==promise2
则会出现死循环,为了为了避免这种情况应该在这里加一层判断
*/
if(x==promise2){
reject(new TypeError('Chaining cycle'));
}else if(x &&typeof x==='function'||typeof x==='object'){
try {
let then = x.then;
/**在这里加上一层判断是为了避免用户传入像{then:""}的对象*/
if(typeof then==='function'){
then.call(x,(y)=>{
if(used)return;
used=true;
resolvePromise(promise2, y, resolve, reject);
},e=>{
if(used)return;
used=true;
reject(e)
})
}else{
if(used)return;
used=true;
resolve(x)
}
} catch (error) {
reject(error)
}
}else{
x&&resolve(x)
}
}
module.exports=Promise
可以参考这位大佬的文章
小邵教你玩转promise