为了能够更好的理解和使用promise,我觉得还是得看一看源码,了解其内部的核心机制 由于Promise内容过多,下面我们由浅入深,一点一点的实现。 本篇篇幅很长,因为我也是一点点写的,要是直接全部写完的代码扔上来,我也看得晕,哈哈加油吧,慢慢看
1.声明Promise并绑定this
let p = new PromiseA((resolve, reject) => {resolve("成功");// reject("失败");});console.log(p);
(1)声明
首先,我们声明一个 PromiseA 来代表我们自己写的promise
我们知道,promise的特性: (1)有三个状态pending,fulfilled,rejected (2)状态一旦改变,后续状态不可改变 定义时,传入一个参数为 resolve 和 rejected 的函数 executor
class PromiseA {static PENDING = "pending";static FULFILLED = "fulfilled";static REJECTED = "rejected";// 按照定义,我们写出promiseconstructor(executor) {this.status = PromiseA.PENDING;this.value = null;// 先不绑定,看看效果executor(this.resolve, this.reject);}// 由于resolve和reject执行时是在promise外部,隐式传递导致this丢失,所以需要另外绑定resolve(value) {this.status = PromiseA.FULFILLED;this.value = value;}reject(reason) {this.status = PromiseA.REJECTED;this.value = reason;}}

resolve和reject不绑定this,就会出现这样的报错,找不到this的status
(2)绑定this 和 保护状态
class PromiseA {static PENDING = "pending";static FULFILLED = "fulfilled";static REJECTED = "rejected";constructor(executor) {this.status = PromiseA.PENDING;this.value = null;// 绑定thisexecutor(this.resolve.bind(this), this.reject.bind(this));}resolve(value) {// 判断一下,如果状态不是pending那么状态以及改变,不能再次改变if (this.status === PromiseA.PENDING) {this.status = PromiseA.FULFILLED;this.value = value;}}reject(reason) {if (this.status === PromiseA.PENDING) {this.status = PromiseA.REJECTED;this.value = reason;}}}
(3)定义时的错误处理
我们知道,如果我们在定义promise时,在状态改变之前出现了错误,这个promise会之间变成reject状态
let p = new Promise((resolve,reject)=>{console.log(abc); // abc未定义,状态变成rejectedresolve("原生成功")})console.log(p);

let p = new PromiseA((resolve, reject) => {console.log(abc);resolve("成功");});console.log(p);

别说状态改变了,后面的代码都执行不了,所以,我们不能因为promise的错误就中断所有代码的执行
class PromiseA {static PENDING = "pending";static FULFILLED = "fulfilled";static REJECTED = "rejected";constructor(executor) {this.status = PromiseA.PENDING;this.value = null;// try catch 捕捉异常try {executor(this.resolve.bind(this), this.reject.bind(this));} catch (error) {this.reject(error)}}resolve(value) {if (this.status === PromiseA.PENDING) {this.status = PromiseA.FULFILLED;this.value = value;}}reject(reason) {if (this.status === PromiseA.PENDING) {this.status = PromiseA.REJECTED;this.value = reason;}}}
2.then方法的基本构建
我们知道then方法有两个参数 onFulfilled 和 onRejected 两个函数 (1)当我们resolve时,then触发onFulfilled (2)当我们reject时,then触发onRejected (3)当 resolve 或 reject 被异步操作延迟时,也就是状态为pending时,then的内部处理 (4)重点:then方法会将onFulfilled 或 onRejected 内产生的错误传递给下一个then或者catch,由于这还没有到链式传递那块,先用try catch代替 (5)then内部执行的函数是异步回调,是异步操作!! (6)还有一个就是我们最容易忽略的点,当 resolve 或 reject 被异步操作延迟时,resolve 或 reject后面的代码应该是同步的,先执行,而不应该是我们then执行完后再执行
(1)构建then
class PromiseA {// ...上面的代码then(onFulfilled, onRejected) {// 防止then中传入的参数为空时报错if (typeof onFulfilled !== "function") {onFulfilled = () => { };}if (typeof onRejected !== "function") {onRejected = () => { };}if (this.status === PromiseA.FULFILLED) {// 直接执行的话就是同步了,使用setTimeOut,变成异步setTimeout(() => {// 我们知道promise内部会将错误传递给下一个then,或者catch处理// 我们这里就先用trycatch处理来模仿一下try {onFulfilled(this.value);} catch (error) {onRejected(error);}});}if (this.status === PromiseA.REJECTED) {setTimeout(() => {try {onRejected(this.value);} catch (error) {onRejected(error);}});}}}
let p = new PromiseA((resolve, reject) => {resolve("成功");});p.then(value => {// 当发送错误时,直接catch到error那处理// console.log(abc);console.log("value:", value);}, error => {console.log("error:", error);})console.log(p);
(2)当状态为pending时,then的处理
当状态为 pending 时,这时候我们的resolve或reject八成是被套在了定时器里变异步了
如果我们不对pending状态进行处理,那么我们写的promise.then就无法处理
let p = new PromiseA((resolve, reject) => {setTimeout(() => {resolve("成功");});});p.then(value => {console.log("value:", value);}, error => {console.log("error:", error);});console.log(p);
(1)使用callback数组处理 和 错误处理
那我们该如何处理pending状态时的then呢?又要如何拿到异步处理完成后,变化的状态呢? (1)其实,我们可以在构造函数内,新增一个 callbacks 数组(队列) 来存储我们未执行的onFulfilled和onRejected (2)然后,当异步任务完成时,触发resolve或reject,我们再通过resolve和reject内部来触发callback,这样我们就能够实现一个 延时状态改变了 (3)当然,在pending状态内部,我们也还是要进行错误的处理
class PromiseA {//...静态属性constructor(executor) {// ... status, valuethis.callbacks = [];// ...executor}resolve(value) {if (this.status === PromiseA.PENDING) {this.status = PromiseA.FULFILLED;this.value = value;// 当异步任务结束,触发resolve状态改变时,调用callbackthis.callbacks.map(callback => {// 上面说的错误问题依然存在,所以要用try-catch捕获try {callback.onFulfilled(this.value);} catch (error) {callback.onRejected(error);}});}}reject(reason) {if (this.status === PromiseA.PENDING) {this.status = PromiseA.REJECTED;this.value = reason;this.callbacks.map(callback => {try {callback.onRejected(this.value);} catch (error) {callback.onRejected(error);}});}}then(onFulfilled, onRejected) {if (typeof onFulfilled !== "function") {onFulfilled = () => { };}if (typeof onRejected !== "function") {onRejected = () => { };}if (this.status === PromiseA.PENDING) {// 当状态为pending,我们把没有执行的onFulfilled和onRejected存储起来// 等待状态的改变再来调用this.callbacks.push({onFulfilled,onRejected});}if (this.status === PromiseA.FULFILLED) {setTimeout(() => {try {onFulfilled(this.value);} catch (error) {onRejected(error);}});}if (this.status === PromiseA.REJECTED) {setTimeout(() => {try {onRejected(this.value);} catch (error) {onRejected(error);}});}}}
(2)resolve和reject后方代码的同步执行问题
如何解决这个问题: 其实我们只需要把callback执行时,把callback变成异步执行就行,这样resolve后面的代码就能先执行了
上面代码写完了之后,看似没有什么问题,但实际上,我们在resolve后面添加一个行代码就能发现问题了
let p = new PromiseA((resolve, reject) => {setTimeout(() => {resolve("成功");console.log("666");});});p.then(value => {console.log("value:", value);}, error => {console.log("error:", error);});console.log(p);

666竟然在then执行完之后才输出,这就很不应该了,它应该是在then执行之前输出的
class PromiseA {// ...constructor(executor) {...}resolve(value) {if (this.status === PromiseA.PENDING) {this.status = PromiseA.FULFILLED;this.value = value;// callback变成异步执行,这样resolve后方的代码就能先执行了setTimeout(() => {this.callbacks.map(callback => {try {callback.onFulfilled(this.value);} catch (error) {callback.onRejected(error);}});});}}reject(reason) {if (this.status === PromiseA.PENDING) {this.status = PromiseA.REJECTED;this.value = reason;setTimeout(() => {this.callbacks.map(callback => {try {callback.onRejected(this.value);} catch (error) {callback.onRejected(error);}});});}}then(onFulfilled, onRejected) {...}}
3.then的链式传递的实现
链式操作其实也就是我们把 onFulfilled 和 onRejected 执行后的结果封装成一个新的promise传给下一个then而已。 (1)把 onFulfilled 和 onRejected 执行后的返回值封装成一个新的promise(resolve,reject) (2)返回值为普通值,直接resolve 或 reject (3)返回值为promise,获得其内部resolve或reject的值,并通过resolve 或 reject传递 (4)注意其内部可能产生的错误,并通过trycatch进行错误处理,完成错误的链式传递 注意: 返回值为promise时,内部的resolve或reject被延迟执行,和上面的情况类似,但实际上,我们上面的步骤就已经帮我们全部处理完了,由于我们是通过调用返回值promise的 then来实现参数传递的,因为返回值为promise,所以我们上面封装的它也有效。(嘿嘿,所以我们不用考虑这个了)
(1)返回值的封装
封装时,要考虑上面说的,返回值为普通值时,和返回值为promise时的情况
class PromiseA {static PENDING = "pending";static FULFILLED = "fulfilled";static REJECTED = "rejected";constructor(executor) {this.status = PromiseA.PENDING;this.value = null;this.callbacks = [];try {executor(this.resolve.bind(this), this.reject.bind(this));} catch (error) {this.reject(error);}}resolve(value) {if (this.status === PromiseA.PENDING) {this.status = PromiseA.FULFILLED;this.value = value;setTimeout(() => {this.callbacks.map(callback => {try {callback.onFulfilled(this.value);} catch (error) {callback.onRejected(error);}});});}}reject(reason) {if (this.status === PromiseA.PENDING) {this.status = PromiseA.REJECTED;this.value = reason;setTimeout(() => {this.callbacks.map(callback => {try {callback.onRejected(this.value);} catch (error) {callback.onRejected(error);}});});}}then(onFulfilled, onRejected) {if (typeof onFulfilled !== "function") {onFulfilled = () => { };}if (typeof onRejected !== "function") {onRejected = () => { };}if (this.status === PromiseA.PENDING) {this.callbacks.push({onFulfilled,onRejected});}if (this.status === PromiseA.FULFILLED) {return new PromiseA((resolve, reject) => {setTimeout(() => {try {let res = onFulfilled(this.value);if (res instanceof PromiseA) {// 如果返回值是 一个promise,则直接调用其then函数// 并且把 我们的resolve传入,当作onFulfilled函数来接收其内部resolve的值res.then(resolve, reject);} else {// 返回值为普通值,则直接resolveresolve(res);}} catch (error) {// onRejected(error);// 错误处理也交给这个新的promise处理,这样就完成了错误的链式传递reject(error);}});});}if (this.status === PromiseA.REJECTED) {return new PromiseA((resolve, reject) => {setTimeout(() => {try {let res = onRejected(this.value);if (res instanceof PromiseA) {res.then(resolve, reject);} else {reject(res);}} catch (error) {reject(error);}});});}}}
// test1let p = new PromiseA((resolve, reject) => {resolve("成功");});p.then(value => {console.log("value:", value);return new PromiseA(resolve => {resolve("666");setTimeout(() => {resolve("666");});});}, error => {console.log("error:", error);}).then(value => {console.log(value);})// test2let p = new PromiseA((resolve, reject) => {resolve("成功");});p.then(value => {console.log("value:", value);return new PromiseA(resolve => {// resolve被延迟时setTimeout(() => {resolve("666");});});}, error => {console.log("error:", error);}).then(value => {console.log(value);})
两次test结果一样,封装成功
let p = new PromiseA((resolve, reject) => {resolve("成功");});p.then(value => {// 测试错误的链式传递console.log(abc);console.log("value:", value);}, error => {console.log("error第一次:", error);}).then(value => {console.log(value);}, error => {console.log("error第二次:", error);})
4.静态方法resolve和reject的构建
到这,我们已经实现了promise的大量功能了 这两个静态方法实际上就是调用我们上面写的就行了,会写then了,这两个就很简单了
实际上,Promise.resolve就直接创建一个新的promise,然后resolve就行 (1)Promise.resolve传入值为普通值 (2)Promise.resolve传入值为promise对象
class PromiseA {static PENDING = "pending";static FULFILLED = "fulfilled";static REJECTED = "rejected";constructor(executor) {this.status = PromiseA.PENDING;this.value = null;this.callbacks = [];try {executor(this.resolve.bind(this), this.reject.bind(this));} catch (error) {this.reject(error);}}resolve(value) {if (this.status === PromiseA.PENDING) {this.status = PromiseA.FULFILLED;this.value = value;setTimeout(() => {this.callbacks.map(callback => {try {callback.onFulfilled(this.value);} catch (error) {callback.onRejected(error);}});});}}reject(reason) {if (this.status === PromiseA.PENDING) {this.status = PromiseA.REJECTED;this.value = reason;setTimeout(() => {this.callbacks.map(callback => {try {callback.onRejected(this.value);} catch (error) {callback.onRejected(error);}});});}}then(onFulfilled, onRejected) {// 防止then中传入的参数为空时报错if (typeof onFulfilled !== "function") {onFulfilled = () => { };}if (typeof onRejected !== "function") {onRejected = () => { };}if (this.status === PromiseA.PENDING) {this.callbacks.push({onFulfilled,onRejected});}if (this.status === PromiseA.FULFILLED) {return new PromiseA((resolve, reject) => {setTimeout(() => {try {let res = onFulfilled(this.value);if (res instanceof PromiseA) {res.then(resolve, reject);} else {resolve(res);}} catch (error) {reject(error);}});});}if (this.status === PromiseA.REJECTED) {return new PromiseA((resolve, reject) => {setTimeout(() => {try {let res = onRejected(this.value);if (res instanceof PromiseA) {res.then(resolve, reject);} else {reject(res);}} catch (error) {reject(error);}});});}}static resolve(value) {return new PromiseA((resolve, reject) => {if (value instanceof PromiseA) {value.then(resolve, reject);} else {resolve(value);}});}static reject(reason) {return new PromiseA((resolve, reject) => {if (reason instanceof PromiseA) {reason.then(resolve, reject);} else {reject(reason);}});}}
// 传入的值为普通值PromiseA.resolve(666).then(value => {console.log("resolve:", value);}, error => {console.log("reject:", error);})PromiseA.reject(666).then(value => {console.log("resolve:", value);}, error => {console.log("reject:", error);})

// 传入的值为promise对象let p = new PromiseA((resolve, reject) => {resolve("成功");// reject("失败");});PromiseA.resolve(p).then(value => {console.log("resolve:", value);}, error => {console.log("reject:", error);});PromiseA.reject(p).then(value => {console.log("resolve:", value);}, error => {console.log("reject:", error);})
5.完整核心代码:
class PromiseA {static PENDING = "pending";static FULFILLED = "fulfilled";static REJECTED = "rejected";constructor(executor) {this.status = PromiseA.PENDING;this.value = null;this.callbacks = [];try {executor(this.resolve.bind(this), this.reject.bind(this));} catch (error) {this.reject(error);}}resolve(value) {if (this.status === PromiseA.PENDING) {this.status = PromiseA.FULFILLED;this.value = value;setTimeout(() => {this.callbacks.map(callback => {try {callback.onFulfilled(this.value);} catch (error) {callback.onRejected(error);}});});}}reject(reason) {if (this.status === PromiseA.PENDING) {this.status = PromiseA.REJECTED;this.value = reason;setTimeout(() => {this.callbacks.map(callback => {try {callback.onRejected(this.value);} catch (error) {callback.onRejected(error);}});});}}then(onFulfilled, onRejected) {// 防止then中传入的参数为空时报错if (typeof onFulfilled !== "function") {onFulfilled = () => { };}if (typeof onRejected !== "function") {onRejected = () => { };}if (this.status === PromiseA.PENDING) {this.callbacks.push({onFulfilled,onRejected});}if (this.status === PromiseA.FULFILLED) {return new PromiseA((resolve, reject) => {setTimeout(() => {try {let res = onFulfilled(this.value);if (res instanceof PromiseA) {res.then(resolve, reject);} else {resolve(res);}} catch (error) {reject(error);}});});}if (this.status === PromiseA.REJECTED) {return new PromiseA((resolve, reject) => {setTimeout(() => {try {let res = onRejected(this.value);if (res instanceof PromiseA) {res.then(resolve, reject);} else {reject(res);}} catch (error) {reject(error);}});});}}static resolve(value) {return new PromiseA((resolve, reject) => {if (value instanceof PromiseA) {value.then(resolve, reject);} else {resolve(value);}});}static reject(reason) {return new PromiseA((resolve, reject) => {if (reason instanceof PromiseA) {reason.then(resolve, reject);} else {reject(reason);}});}}
整了Promise源码真的很累,从看源码到整理思路,再到写完博客,花了我好几天,求求各位点一个赞吧👍!!
成功打印
最后成功执行

成功的输出了
成功把错误传给了下一个then
