实现一个promise我个人分为几步
- 定义状态和值
- 初始化状态和值
- 实现resolve和reject方法来改变状态,这里需要注意报错处理和状态确定后就不可改变和this指向问题
- 定义任务队列保存下需要执行的函数,在状态改变时去执行
- 实现then 执行任务队列,需要判断传入参数不为function 为function和返回一个promise的情况
个人感觉promise源码难点在于状态的透传和切换执行成功和失败的方法
const state = {pending: 0, // 等待fulfilled: 1, // 成功rejected: 2, // 错误}// 创建一个"微任务"const runMicroTask = (fn) => {// 实际上setTimeout并不加入微任务队列,会加入延时队列(w3c已不再推荐使用宏任务微任务来描述)// 这里重点是promise所以暂且就使用setTimeout代替,也可以使用MutationObserver来真正的加入到微任务队列setTimeout(fn, 0)}// 如何判断是promise,按照promise A+ 规范来说 一个对象有then 并且是一个方法 那就是一个promiseconst isPromise = (obj) => {return !!(obj && typeof obj === "object" && typeof obj.then === "function")}class myPromise {constructor (executor) {// 初始化为等待状态this._state = state.pendingthis._value = null// 定义任务队列 在状态改变的时候循环执行里面保存的函数this.handleList = []try {// 创建promise会同步执行一次executor(this.resolve, this.reject)} catch (error) {// 执行出错的处理this.reject(error)}}// 抽离出一个修改状态的方法setState = (state, value) => {if (state === state.pending) {return }this._state = statethis._value = value// 循环执行任务队列this.runHandleList()}// 成功resolve = (value) => {this.setState(state.fulfilled, value)}// 错误reject = (value) => {this.setState(state.rejected, value)}// then接收两个参数 一个为成功执行的函数一个为失败执行的函数then = (handleFulfilled,handleRejected) => {// 之所以可以链式调用就是因为返回了myPromise类 里面有then方法 return new myPromise((resolve, reject) => {// 传入handleFulfilled 成功处理函数 handleRejected 错误处理函数 // 传入resolve reject来确定当前函数执行后的状态 成功就调用resolve失败执行rejectthis.pushHandleItem({handleFulfilled, handleRejected, resolve, reject})// 这里执行是应为 当前状态可能已经确定了 所以要检查一下this.runHandleList()})}// 把函数加入任务队列pushHandleItem = ({handleFulfilled, handleRejected, resolve, reject}) => {this.handleList.push({handle: handleFulfilled, state: state.fulfilled, resolve, reject})this.handleList.push({handle: handleRejected, state: state.rejected, resolve, reject})}runHandleList = () => {if (this._state === state.pending) {return}this.handleList.forEach(item => {// 放入微任务runMicroTask(this.runOneHandleItem(item))})// 执行完成后清空队列this.handleList = []}runOneHandleItem = ({handle, state: itemState, resolve, reject}) => {// 状态不匹配不做处理if (this._state !== itemState) returnif (typeof handle !== 'function') { // 状态透传itemState === state.fulfilled ? resolve(this._value) : reject(this._value)return}try {const val = handle(this._value)// 判断当前是否返回一个Promise如果是就调用自身的then方法把当前的状态交给返回的Promise处理if (isPromise(val)) {val.then(resolve, reject)} else {// 值透传resolve(val)}} catch (error) {// 失败时的处理reject(error)}}// catch直接调用then即可catch = (onRejected) => {return this.then(undefined, onRejected);};}const pro = new myPromise((resolve, reject) => {resolve('222222222')})pro.then(res => {console.log(res)return new myPromise((resolve, reject) => {reject('3333333333333333')})}).then(res => {console.log(res)}).catch(err => {console.log('err', err)})console.log(pro)
有不足和错误的地方望大佬指出我会及时修正