一步步实现一个Promise
-
平常用promise的时候, 是通过new关键字来new Promise(), 用构造函数或者class
class MPromise { constructor() { } } -
定义promise三种状态类型
const PENDING = 'pending' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' -
设置初始状态
class MPromise { constructor() { // 初始状态为pending this.status = PENDING this.value = null this.reason = null } } -
resolve 和 reject 方法
- 这两个方法是要更改status的, 从pending改到fulfilled/rejected.
- 两个函数的入参分别是value 和 reason.
class MPromise { constructor() { // 初始状态为pending this.status = PENDING this.value = null this.reason = null } resolve(value) { if (this.status === PENDING) { this.value = value this.status = FULFILLED } } reject(reason) { if (this.status === PENDING) { this.reason = reason this.status = REJECTED } } } -
promise入参
- 入参是一个excutor函数, 函数接收resolve和reject两个参数.
- 注意在初始化promise的时候, 就要执行excutor, 并且有任何报错都要通过reject抛出去
class MPromise { constructor(fn) { // 初始状态为pending this.status = PENDING this.value = null this.reason = null try { // 通过bind改变this指向该promise fn(this.resolve.bind(this), this.reject.bind(this)) } catch (e) { this.reject(e) } } resolve(value) { if (this.status === PENDING) { this.value = value this.status = FULFILLED } } reject(reason) { if (this.status === PENDING) { this.reason = reason this.status = REJECTED } } } -
接下来来实现一下关键的then方法
-
then接收两个参数, onFulfilled 和 onRejected
then(onFulfilled, onRejected) {} -
检查并处理参数, 之前提到的如果不是function, 就忽略. 这个忽略指的是原样返回value或者reason.【值穿透】
isFunction(param) { return typeof param === 'function' } then(onFulfilled, onRejected) { const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => { return value } const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => { throw reason } } -
.then的返回值整体是一个promise, 所以咱们先用promise来包裹一下, 其他逻辑待会再实现.
then(onFulfilled, onRejected) { const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => { return value } const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => { throw reason } const promise2 = new MPromise((resolve, reject) => {}) return promise2 } -
根据当前promise的状态, 调用不同的函数
then(onFulfilled, onRejected) { const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => { return value } const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => { throw reason } const promise2 = new MPromise((resolve, reject) => { switch (this.status) { case FULFILLED: { realOnFulfilled() break } case REJECTED: { realOnRejected() break } } }) return promise2 } -
这个时候在then函数被调用的瞬间就会执行. 那这时候如果status还没变成fulfilled或者rejected,很有可能还是pending的. 所以我们需要一个状态的监听机制, 当状态变成fulfilled或者rejected后, 再去执行callback.
-
那么我们首先要拿到所有的callback, 然后才能在某个时机去执行他. 新建两个数组, 来分别存储成功和失败的回调, 调用then的时候, 如果还是pending就存入数组.
FULFILLED_CALLBACK_LIST = [] REJECTED_CALLBACK_LIST = [] then(onFulfilled, onRejected) { const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => { return value } const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => { throw reason } const promise2 = new MPromise((resolve, reject) => { switch (this.status) { case FULFILLED: { realOnFulfilled() break } case REJECTED: { realOnRejected() break } case PENDING: { // p.then();p.then();p.then().... this.FULFILLED_CALLBACK_LIST.push(realOnFulfilled) this.REJECTED_CALLBACK_LIST.push(realOnRejected) } } }) return promise2 } -
在status发生变化的时候, 就执行所有的回调. 这里用一下es6的getter和setter. 这样更符合语义, 当status改变时, 去做什么事情. (当然也可以顺序执行, 在给status赋值后, 下面再加一行forEach)
_status = PENDING get status() { return this._status } set status(newStatus) { this._status = newStatus switch (newStatus) { case FULFILLED: { this.FULFILLED_CALLBACK_LIST.forEach(callback => { callback(this.value) }) break } case REJECTED: { this.REJECTED_CALLBACK_LIST.forEach(callback => { callback(this.reason) }) break } } }
-
-
-
then的返回值
上面只是简单说了下, then的返回值是一个Promise, 那么接下来具体讲一下返回promise的value和reason是什么.
-
如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e。(这样的话, 我们就需要手动catch代码,遇到报错就reject)
then(onFulfilled, onRejected) { const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => { return value } const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => { throw reason } const promise2 = new MPromise((resolve, reject) => { const fulfilledMicrotask = () => { try { realOnFulfilled(this.value) } catch (e) { reject(e) } } const rejectedMicrotask = () => { try { realOnRejected(this.reason) } catch (e) { reject(e) } } switch (this.status) { case FULFILLED: { fulfilledMicrotask() break } case REJECTED: { rejectedMicrotask() break } case PENDING: { this.FULFILLED_CALLBACK_LIST.push(fulfilledMicrotask) this.REJECTED_CALLBACK_LIST.push(rejectedMicrotask) } } }) return promise2 } -
如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值
-
如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因。
需要注意的是,如果promise1的onRejected执行成功了,promise2应该被resolve
这里咱们其实已经在参数检查的时候做过了, 也就是这段代码
const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => { return value } const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => { throw reason } -
-
如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行resolvePromise方法
then(onFulfilled, onRejected) { const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : (value) => { return value } const realOnRejected = this.isFunction(onRejected) ? onRejected : (reason) => { throw reason } const promise2 = new MPromise((resolve, reject) => { const fulfilledMicrotask = () => { try { const x = realOnFulfilled(this.value) this.resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } } const rejectedMicrotask = () => { try { const x = realOnRejected(this.reason) this.resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } } switch (this.status) { case FULFILLED: { fulfilledMicrotask() break } case REJECTED: { rejectedMicrotask() break } case PENDING: { this.FULFILLED_CALLBACK_LIST.push(fulfilledMicrotask) this.REJECTED_CALLBACK_LIST.push(rejectedMicrotask) } } }) return promise2 } -
resolvePromise
resolvePromise(promise2, x, resolve, reject) { // 如果 newPromise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 newPromise // 这是为了防止死循环 if (promise2 === x) { return reject(new TypeError('The promise and the return value are the same')) } if (x instanceof MPromise) { // 如果 x 为 Promise ,则使 newPromise 接受 x 的状态 // 也就是继续执行x,如果执行的时候拿到一个y,还要继续解析y queueMicrotask(() => { x.then((y) => { this.resolvePromise(promise2, y, resolve, reject) }, reject) }) } else if (typeof x === 'object' || this.isFunction(x)) { // 如果 x 为对象或者函数 if (x === null) { // null也会被判断为对象 return resolve(x) } let then = null try { // 把 x.then 赋值给 then then = x.then } catch (error) { // 如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise return reject(error) } // 如果 then 是函数 if (this.isFunction(then)) { let called = false // 将 x 作为函数的作用域 this 调用 // 传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise try { then.call( x, // 如果 resolvePromise 以值 y 为参数被调用,则运行 resolvePromise (y) => { // 需要有一个变量called来保证只调用一次. if (called) return called = true this.resolvePromise(promise2, y, resolve, reject) }, // 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise (r) => { if (called) return called = true reject(r) }) } catch (error) { // 如果调用 then 方法抛出了异常 e: if (called) return // 否则以 e 为据因拒绝 promise reject(error) } } else { // 如果 then 不是函数,以 x 为参数执行 promise resolve(x) } } else { // 如果 x 不为对象或者函数,以 x 为参数执行 promise resolve(x) } } -
onFulfilled 和 onRejected 是微任务
咱们可以用queueMicrotask包裹执行函数
const fulfilledMicrotask = () => { queueMicrotask(() => { try { const x = realOnFulfilled(this.value) this.resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }) } const rejectedMicrotask = () => { queueMicrotask(() => { try { const x = realOnRejected(this.reason) this.resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e) } }) } -
catch方法
catch (onRejected) { return this.then(null, onRejected) } -
Promise.resolve
将现有对象转为Promise对象,如果 Promise.resolve 方法的参数,不是具有 then 方法的对象(又称 thenable 对象),则返回一个新的 Promise 对象,且它的状态为fulfilled。
注意这是一个静态方法, 因为咱们是通过Promise.resolve调用的, 而不是通过实例去调用的.static resolve(value) { if (value instanceof MPromise) { return value } return new MPromise((resolve) => { resolve(value) }) } -
Promise.reject
返回一个新的Promise实例,该实例的状态为rejected。Promise.reject方法的参数reason,会被传递给实例的回调函数。
static reject(reason) { return new MPromise((resolve, reject) => { reject(reason) }) } -
promise.all
const p = Promise.all([p1, p2, p3])数组中的元素可以是promise,可以不是promise.在数组中所有promise执行完毕后返回结果,结果是一个新的promise, 只有所有的promise都成功才成功, 只要有一个失败了就失败
static all(promises) { //用来保存所有成功value的数组 const res= [] //用来保存成功promise的数量 let resolveCount = 0 //返回新的promise return new MPromise((resolve, reject) => { if(!Array.isArray(promises)){ return reject(new Error('参数输入错误')) } //遍历promises获取每个promise的结果 promises.forEach((p, index) => { MPromise.resolve(p).then( //p可以是数值 value => { resolveCount++ //成功数量加1 //p成功,将成功的value保存进res // res中保存的结果应该与promises数组中的每一个promise相对应的,所以不能用res.push(value) res[index] = value // 如果全部成功,将return的promise改为成功 if (resolveCount === promises.length) { resolve(res) } }, reason => { //只有一个失败,return的promise就失败 reject(reason) //无论reject还是resolve都只会执行一次,因为一个promise的结果一旦确定(resolved or rejected),就不可改 } ) }) }) } -
promise.race
const p = Promise.race([p1, p2, p3])该方法是将多个 Promise 实例,包装成一个新的 Promise 实例。
只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。static race(promises) { return new MPromise((resolve, reject) => { const length = promises.length if (length === 0) { return resolve() } else { promises.forEach((p)=>{ MPromise.resolve(p).then( (value) => { return resolve(value) }, (reason) => { return reject(reason) } ) }) } }) }
实现Promise的原理与细节解析
本文详细讲解了如何一步步实现Promise,包括其构造函数、状态管理、resolve和reject方法、then方法的处理逻辑、微任务调度以及catch方法、Promise.resolve和Promise.reject的使用。此外,还介绍了Promise.all和Promise.race的功能和实现方式。
351

被折叠的 条评论
为什么被折叠?



