手写Promise源码的实现思路
创始人
2025-06-01 13:30:48

Promise的使用:

let promise = new Promise((resolve, reject) => {resolve("OK");// reject("Error");
});console.log(promise);promise.then(value => {console.log("success");
}, error => {console.log("fail");
});
  1. 定义构造函数中的两个基本属性PromiseStatePromiseResult

    function Promise() {this.PromiseState = "pending";this.PromiseResult = null;
    }
    
  2. 由于实例对象中传递的参数是一个执行器函数,并且会立即执行这个函数。

    function Promise(executor) {this.PromiseState = "pending";this.PromiseResult = null;executor();
    }
    
  3. 该执行器函数中有两个函数参数,调用任意一个函数会改变promise的状态和结果值,且状态只能改变一次。

    function Promise(executor) {this.PromiseState = "pending";this.PromiseResult = null;// 防止this指向windowconst self = this;function resolve(value) {if(self.PromiseState !== "pending") return;self.PromiseState = "fulfilled";self.PromiseResult = value;}function reject(reason) {if(self.PromiseState !== "pending") return;self.PromiseState = "rejected";self.PromiseResult = reason;}// 参数为一个函数且立即执行,该函数需要两个函数参数改变promise的状态和结果值executor(resolve, reject);
    }
    
  4. 还有一种情况:promise实例执行结果为抛出异常,需要让其状态为失败。

    function Promise(executor) {// ...// 参数为一个函数且立即执行,该函数需要两个函数参数改变promise的状态和结果值;抛出异常时状态为失败try {executor(resolve, reject);} catch (error) {reject(error);}
    }
    
  5. 在对象原型上添加then方法。

    Promise.prototype.then = function(onResolved, onRejected) {if(this.PromiseState === "fulfilled") {onResolved();}if(this.PromiseState === "rejected") {onRejected();}
    }
    
  6. executor的执行内容是异步的,应该等到异步执行后改变了状态才能执行then中的回调函数,异步执行前状态还是为pending

    let promise = new Promise((resolve, reject) => {setTimeout(()=> {resolve("OK");}, 1000);
    });
    
    function Promise(executor) {// ...this.callback = null;// 防止this指向windowconst self = this;function resolve(value) {if(self.PromiseState !== "pending") return;self.PromiseState = "fulfilled";self.PromiseResult = value;if(self.callback.onResolved) {self.callback.onResolved();}}function reject(reason) {if(self.PromiseState !== "pending") return;self.PromiseState = "rejected";self.PromiseResult = reason;if(self.callback.onRejected) {self.callback.onRejected();}}// ...
    }// then方法
    Promise.prototype.then = function(onResolved, onRejected) {// ...if(this.PromiseState === "pending") {// 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来this.callback = {onResolved,onRejected};}
    }
    
  7. 当一个Promise实例执行了多个then方法时,两个then里的方法都会执行。

    let promise = new Promise((resolve, reject) => {resolve("OK");
    });promise.then(value => {console.log("success");
    }, error => {console.log("fail");
    });promise.then(value => {console.log("success2");
    }, error => {console.log("fail2");
    });
    // success success2
    
    function Promise(executor) {// ...this.callback = null;// 防止this指向windowconst self = this;function resolve(value) {if(self.PromiseState !== "pending") return;self.PromiseState = "fulfilled";self.PromiseResult = value;self.callbacks.forEach(item => {item.onResolved();});}function reject(reason) {if(self.PromiseState !== "pending") return;self.PromiseState = "rejected";self.PromiseResult = reason;self.callbacks.forEach(item => {item.onRejected();});}// ...
    }// then方法
    Promise.prototype.then = function(onResolved, onRejected) {// ...if(this.PromiseState === "pending") {// 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来this.callbacks.push({onResolved,onRejected});}
    }
    
  8. then方法返回的也是一个Promise实例,这个实例的状态由执行的回调函数的结果来决定,如果回调函数的执行内容是非Promise实例,则都为成功状态;如果是Promise实例,状态根据这个实例的状态来定。

    • executor执行内容为同步时:

      Promise.prototype.then = function(onResolved, onRejected) {const self = this;return new Promise((resolve, reject) => {if(self.PromiseState === "fulfilled") {// 拿到回调函数的返回值// Promise实例:根据其结果状态决定then执行后该实例的状态;非Promise实例:状态都为成功const result = onResolved(self.PromiseResult);if(result instanceof Promise) {// 既然是一个Promise实例,就能根据该实例的执行内容确定状态result.then(v => {resolve(v);}, r => {reject(r);});} else {resolve(result);}}if(self.PromiseState === "rejected") {// 同上const result = onRejected(self.PromiseResult);if(result instanceof Promise) {result.then(v => {resolve(v);}, r => {reject(r);});} else {resolve(result);}}}// ...})
      }
      
    • executor执行内容为异步时:

      Promise.prototype.then = function(onResolved, onRejected) {const self = this;return new Promise((resolve, reject) => {// ...if(self.PromiseState === "pending") {// 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来self.callbacks.push({onResolved: function() {// 同上const result = onResolved(self.PromiseResult);if(result instanceof Promise) {result.then(v => {resolve(v);}, r => {reject(r);});} else {resolve(result);}},onRejected: function() {// 同上const result = onRejected(self.PromiseResult);if(result instanceof Promise) {result.then(v => {resolve(v);}, r => {reject(r);});} else {resolve(result);}}});}})
      }
      
  9. 封装then方法中出现的重复代码,并处理

    Promise.prototype.then = function(onResolved, onRejected) {const self = this;return new Promise((resolve, reject) => {// 封装函数:根据结果改变状态function callback(fn) {try {// 拿到回调函数的返回值// Promise实例:根据其结果状态决定then执行后该实例的状态;非Promise实例:状态都为成功let result = fn(self.PromiseResult);if(result instanceof Promise) {// 既然是一个Promise实例,就能根据该实例的执行内容确定状态result.then(v => {resolve(v);}, r => {reject(r);});} else {resolve(result);}} catch (error) {reject(error);}}if(self.PromiseState === "fulfilled") {callback(onResolved);}if(self.PromiseState === "rejected") {callback(onRejected);}if(self.PromiseState === "pending") {// 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来self.callbacks.push({onResolved: function() {callback(onResolved);},onRejected: function() {callback(onRejected);}});}})
    }
    
  10. 添加catch方法并实现异常穿透,同时实现then只传递一个参数和不传递参数的情况。

    // 使用
    promise.then(value => {return new Promise((resolve, reject) => {reject("111 error")})
    }).then((value) => {console.log(222)
    }).catch(err => {console.log("err-------------")console.log(err)
    });
    
    // then方法
    Promise.prototype.then = function(onResolved, onRejected) {const self = this;// 不传第二个函数时,默认函数为一个抛出异常操作if(typeof onRejected !== "function") {onRejected = reason => {throw reason;}}// 不传第一个函数时,默认将实例结果值返回,可以实现成功时的值传递if(typeof onResolved !== "function") {onResolved = value => value;}return new Promise((resolve, reject) => {// ...})
    }// catch方法
    Promise.prototype.catch = function(onRejected) {return this.then(undefined, onRejected);
    }
    
  11. 添加Promise.resolvePromisereject方法。

    // resolve方法:根据传入参数的类型决定结果的状态
    Promise.resolve = function(value) {return new Promise((resolve, reject) => {if(value instanceof Promise) {// 既然是一个Promise实例,就能根据该实例的执行内容确定状态value.then(v => {resolve(v);}, r => {reject(r);});} else {resolve(value);}})
    }// reject方法:无论传入的参数是什么类型,结果都是失败状态
    Promise.reject = function(reason) {return new Promise((resolve, reject) => {reject(reason);})
    }
    
  12. 添加Promise.all方法:所有实例都成功则为成功,结果值为所有实例结果值组成的数组;有一个失败,则为失败,结果值为失败的实例的结果值。

    Promise.all = function(promises) {return new Promise((resolve, reject) => {let count = 0,resultArr = [];promises.forEach((item, index) => {item.then(v => {count++;// 按实例的索引值存储其对应结果resultArr[index] = item.PromiseResult;// 全部都为成功时为成功if(count === promises.length) {resolve(resultArr);}}, r => {reject(r);});});})
    }
    
  13. 添加Promise.race方法:实例中谁先改变状态,返回的状态和结果值就为该实例的状态和结果值。

    Promise.race = function(promises) {return new Promise((resolve, reject) => {promises.forEach(item => {item.then(v => {resolve(v);}, r => {reject(r);});});})
    }
    
  14. then方法是一个异步任务。

    function Promise(executor) {// ...// 防止this指向windowconst self = this;function resolve(value) {// ...setTimeout(() => {self.callbacks.forEach(item => {item.onResolved();});});}function reject(reason) {// ...setTimeout(() => {self.callbacks.forEach(item => {item.onRejected();});});}// 参数为一个函数且立即执行,该函数需要两个函数参数改变promise的状态和结果值;抛出异常时状态为失败try {executor(resolve, reject);} catch (error) {reject(error);}
    }// then方法
    Promise.prototype.then = function(onResolved, onRejected) {// ...return new Promise((resolve, reject) => {// ...if(self.PromiseState === "fulfilled") {setTimeout(() => {callback(onResolved);});}if(self.PromiseState === "rejected") {setTimeout(() => {callback(onRejected);});}// ...})
    }
    

调整一下代码结构,整个promise.js源码如下:

function Promise(executor) {this.PromiseState = "pending";this.PromiseResult = null;this.callbacks = [];// 防止this指向windowconst self = this;function resolve(value) {if(self.PromiseState !== "pending") return;self.PromiseState = "fulfilled";self.PromiseResult = value;setTimeout(() => {self.callbacks.forEach(item => {item.onResolved();});});}function reject(reason) {if(self.PromiseState !== "pending") return;self.PromiseState = "rejected";self.PromiseResult = reason;setTimeout(() => {self.callbacks.forEach(item => {item.onRejected();});});}// 参数为一个函数且立即执行,该函数需要两个函数参数改变promise的状态和结果值;抛出异常时状态为失败try {executor(resolve, reject);} catch (error) {reject(error);}
}// then方法
Promise.prototype.then = function(onResolved, onRejected) {// 不传第一个函数时,默认将实例结果值返回,可以实现成功时的值传递if(typeof onResolved !== "function") {onResolved = value => value;}// 不传第二个函数时,默认函数为一个抛出异常操作if(typeof onRejected !== "function") {onRejected = reason => {throw reason;}}const self = this;return new Promise((resolve, reject) => {// 封装函数:根据结果改变状态function callback(fn) {try {// 拿到回调函数的返回值// Promise实例:根据其结果状态决定then执行后该实例的状态;非Promise实例:状态都为成功let result = fn(self.PromiseResult);if(result instanceof Promise) {// 既然是一个Promise实例,就能根据该实例的执行内容确定状态result.then(v => {resolve(v);}, r => {reject(r);});} else {resolve(result);}} catch (error) {reject(error);}}if(self.PromiseState === "pending") {// 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来self.callbacks.push({onResolved: function() {callback(onResolved);},onRejected: function() {callback(onRejected);}});} else if(self.PromiseState === "fulfilled") {setTimeout(() => {callback(onResolved);});} else if(self.PromiseState === "rejected") {setTimeout(() => {callback(onRejected);});}})
}// catch方法
Promise.prototype.catch = function(onRejected) {return this.then(undefined, onRejected);
}// resolve方法:根据传入参数的类型决定结果的状态
Promise.resolve = function(value) {return new Promise((resolve, reject) => {if(value instanceof Promise) {// 既然是一个Promise实例,就能根据该实例的执行内容确定状态value.then(v => {resolve(v);}, r => {reject(r);});} else {resolve(value);}})
}// reject方法:无论传入的参数是什么类型,结果都是失败状态
Promise.reject = function(reason) {return new Promise((resolve, reject) => {reject(reason);})
}// all方法
Promise.all = function(promises) {return new Promise((resolve, reject) => {let count = 0,resultArr = [];promises.forEach((item, index) => {item.then(v => {count++;// 按实例的索引值存储其对应结果resultArr[index] = item.PromiseResult;// 全部都为成功时为成功if(count === promises.length) {resolve(resultArr);}}, r => {reject(r);});});})
}// race方法
Promise.race = function(promises) {return new Promise((resolve, reject) => {promises.forEach(item => {item.then(v => {resolve(v);}, r => {reject(r);});});})
}

相关内容

热门资讯

漂移是什么意思(摇杆漂移是什么... 本篇文章极速百科给大家谈谈漂移是什么意思,以及摇杆漂移是什么意思对应的知识点,希望对各位有所帮助,不...
车架号后四位是什么(车架号后四... 本篇文章极速百科给大家谈谈车架号后四位是什么,以及车架号后四位是什么在哪里看对应的知识点,希望对各位...
隐形眼镜基弧是什么意思,请问,... 隐形眼镜基弧是什么意思目录隐形眼镜基弧是什么意思请问,配隐形眼镜的时候要不要关注那个基弧?隐形眼镜基...
广西省崇左市属于什么市,祟左是... 广西省崇左市属于什么市目录广西省崇左市属于什么市祟左是地级市还是县级市崇左是南宁得直辖市吗 为什么区...
内衣尺码大小分类,内衣的型号分... 内衣尺码大小分类目录内衣尺码大小分类内衣的型号分哪几种?什么abc事什么意思?34、36是尺寸嘛?内...
几个防止卫生间反味小妙招,卫生... 几个防止卫生间反味小妙招目录几个防止卫生间反味小妙招卫生间反臭怎么办?卫生间怎么样防臭几个防止卫生间...
庄子中的成语和解释,四个出自《... 庄子中的成语和解释目录庄子中的成语和解释四个出自《庄子》的成语及解释《庄子》中的成语及解释(按篇目分...
怎么切翡翠原石(收玉石的联系方... 本篇文章极速百科给大家谈谈怎么切翡翠原石,以及收玉石的联系方式对应的知识点,希望对各位有所帮助,不要...
关于燕子的古诗,描写燕子的古诗... 关于燕子的古诗目录关于燕子的古诗描写燕子的古诗描写燕子的古诗有哪些?关于燕子的古诗关于燕子的古诗 ...
好巧不巧是什么意思,好巧不巧什... 好巧不巧是什么意思目录好巧不巧是什么意思好巧不巧什么意思?“无巧不巧”究竟何解?好巧不巧是什么意思好...
关东煮里面放什么配料啊,关东煮... 关东煮里面放什么配料啊目录关东煮里面放什么配料啊关东煮的配料关东煮需要哪些调味料呀?请问,关东煮都可...
极速进化满电出发!长安深蓝SL... 本篇文章极速百科给大家谈谈极速进化满电出发!长安深蓝SL03开启预售,以及长安蓝鲸plus新车报价对...
比亚迪f3汽车报价(比亚迪f3... 今天给各位分享比亚迪f3汽车报价的知识,其中也会对比亚迪f3价格及图片易车进行解释,如果能碰巧解决你...
两台电脑怎么共享一台打印机,两... 两台电脑怎么共享一台打印机目录两台电脑怎么共享一台打印机两台电脑如何共享一台打印机?请问一个打印机怎...
16个复韵母有哪些(16个复韵... 本篇文章极速百科给大家谈谈16个复韵母有哪些,以及16个复韵母怎么读拼音视频对应的知识点,希望对各位...
樟树有什么作用,樟树有什么作用... 樟树有什么作用目录樟树有什么作用樟树有什么作用?樟树的用途有哪些?樟树有什么作用?樟树有什么作用 ...
dazl启动子的作用,启动子和... dazl启动子的作用目录dazl启动子的作用启动子和终止子是什么作用的?dazl启动子的作用启动子的...
写字楼是干什么的 极速百科网 ... 写字楼是干什么的目录写字楼是干什么的写字楼是干什么的写字楼是干什么的 写字楼的功能介绍写字楼是干什么...
骄傲的两种解释,骄傲的意思是什... 骄傲的两种解释目录骄傲的两种解释骄傲的意思是什么?骄傲的两种解释骄傲的两种解释 “骄傲”有两个...
jp是哪个国家的缩写(jp是哪... 本篇文章极速百科给大家谈谈jp是哪个国家的缩写,以及jp是哪个国家的缩写名字对应的知识点,希望对各位...
苹果手机显示不支持此配件怎么办... 不支持此配件怎么解决 苹果iphone可能不支持此配件怎么办怎么解除不支持此配件 不支持此配件怎么解...
支付宝借呗的利息是多少,蚂蚁借... 支付宝借呗的利息是多少目录支付宝借呗的利息是多少蚂蚁借呗利息是怎么计算的蚂蚁借呗的利息是多少借呗的利...
关于兰字的词语或成语越多越好.... 关于兰字的词语或成语越多越好.目录关于兰字的词语或成语越多越好.有关兰字的成语有哪些关于兰的词语或成...
宝马m5多少钱是不是很贵呢?(... 本篇文章极速百科给大家谈谈宝马m5多少钱是不是很贵呢?,以及宝马m5li多少钱对应的知识点,希望对各...
辽宁省喀左县在哪个城市,辽宁省... 辽宁省喀左县在哪个城市目录辽宁省喀左县在哪个城市辽宁省朝阳市喀左县的邮政编码辽宁省喀左县在哪里辽宁省...
关于marcjacobs香水,... 关于marcjacobs香水目录关于marcjacobs香水marcjacobs香水(探索时尚与艺术...
四级英语考试时间分配,大学英语... 四级英语考试时间分配目录四级英语考试时间分配大学英语四级考多长时间?英语四级考试时间安排?英语四级考...
dnfbuff强化有什么用,地... dnfbuff强化有什么用目录dnfbuff强化有什么用地下城buff强化栏DNF中人物的Buff有...
幼儿园孩子新年祝福语简短,适合... 幼儿园孩子新年祝福语简短目录幼儿园孩子新年祝福语简短适合幼儿园小朋友说的新年祝福语幼儿园老师给小朋友...
正断层有哪些断层组合类型,断层... 正断层有哪些断层组合类型目录正断层有哪些断层组合类型断层的组合类型简答题 断层的类型及组合形式有哪些...