手撕Promise
2023-12-27 17:07:04
实现一个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 并且是一个方法 那就是一个promise
const isPromise = (obj) => {
return !!(obj && typeof obj === "object" && typeof obj.then === "function")
}
class myPromise {
constructor (executor) {
// 初始化为等待状态
this._state = state.pending
this._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 = state
this._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失败执行reject
this.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) return
if (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)
有不足和错误的地方望大佬指出我会及时修正
文章来源:https://blog.csdn.net/JasonAlonk/article/details/135248415
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!