前言
本人学习promise原理时,百度了不少相关文章,看的云里雾的。最终决定去PromiseA+的官网看规范,思考一番发现其实并没有那么绕。希望本篇能帮到你更好的理解promise的实现。
Promise规范
按照 PromiseA+ 规范来实现,手写Promise也没那么难。
重点规范(很重要)
-
promise三种状态
- pending:等待状态,可以转为fulfilled或rejected。
- fulfilled:成功状态,不能再转为其他状态,且必须有一个返回值,返回值不能被修改。
- rejected:失败状态,不能再转为其他状态,且必须有一个失败原因,失败原因不能修改。
-
then方法
-
then有两个回调如入参,onFulfilled,onRejected,且两个回调必须为函数,否则忽略。
- onFulfilled必须在promise状态为fulfilled后调用,且只能调用一次。
- onRejected必须在promise状态为rejecte后调用,且只能调用一次。
-
then方法的返回值必须是一个新的promise
-
then方法可以被调用多次
-
promise的结果一定不是promise
-
编码实现(这里只考虑fulfilled状态的实现)
定义基本的骨架
(function (global) {
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
const queueMicrotask = global.queueMicrotask || (task => setTimeout(task))
function resolve(value) {
}
function reject(reason) {
}
class Promise {
state = PENDING
result = undefined
reason = undefined
onSuccesss = []
onFail = []
constructor(executor) {
if (typeof executor === "function") {
executor(resolve.bind(this), reject.bind(this))
} else {
throw new Error('executor must be function!!!')
}
}
then(onFulfilled, onRejected) {
}
}
global.MyPromise = Promise
})(window)
实现resolve方法
根据规范,promise的结果一定不为promise,所以这里要判断情况
function resolve(value) {
if (value instanceof Promise) {
value.then(result => {
this.state = FULFILLED
this.result = result
while (this.onSuccesss.length) {
this.onSuccesss.shift()(this.result)
}
})
} else {
this.state = FULFILLED
this.result = value
while (this.onSuccesss.length) {
this.onSuccesss.shift()(this.result)
}
}
}
重构一下resolve方法,提取重复代码
function resolve(value) {
const task = result => {
this.state = FULFILLED
this.result = result
while (this.onSuccesss.length) {
this.onSuccesss.shift()(this.result)
}
}
value instanceof Promise ? value.then(task) : task(value)
}
实现then方法
- then方法的onFulfilled回调存在两个情况被调用,状态为fulfilled时可以直接调用,pending时要存起来,在resolve中调用。
- onFulfilled,onRejected如果不为函数则忽略
先处理fulfilled状态的情况
then(onFulfilled, onRejected) {
const { state, result } = this
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
onRejected = typeof onRejected === 'function' ? onRejected : v => v
if (state === FULFILLED) {
const data = onFulfilled(result)
return new Promise(resolve => resolve(data))
} else if (state === PENDING) {
}
}
再处理状态为pending的情况,这里要注意onFulfilled并不是立马调用,而是要在状态转为fulfilled后调用,所以封为函数,先存在onSuccesss中
then(onFulfilled, onRejected) {
const { state, result } = this
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
onRejected = typeof onRejected === 'function' ? onRejected : v => v
if (state === FULFILLED) {
const data = onFulfilled(result)
return new Promise(resolve => resolve(data))
} else if (state === PENDING) {
return new Promise(resolve => {
this.onSuccesss.push(res => {
const data = onFulfilled(res)
resolve(data)
})
})
}
}
最后放入微任务队列中,简化一下代码
then(onFulfilled, onRejected) {
const { state, result } = this
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
onRejected = typeof onRejected === 'function' ? onRejected : v => v
if (state === FULFILLED) {
return new Promise(resolve => queueMicrotask(() => resolve(onFulfilled(result))))
} else if (state === PENDING) {
return new Promise(resolve => this.onSuccesss.push(res => queueMicrotask(() => resolve(onFulfilled(res)))))
}
}
最终代码
(function (global) {
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
const queueMicrotask = global.queueMicrotask || (task => setTimeout(task))
function resolve(value) {
const task = result => {
this.state = FULFILLED
this.result = result
while (this.onSuccesss.length) {
this.onSuccesss.shift()(this.result)
}
}
value instanceof Promise ? value.then(task) : task(value)
}
function reject(reason) { }
class Promise {
state = PENDING
result = undefined
reason = undefined
onSuccesss = []
onFails = null
constructor(executor) {
if (typeof executor === "function") {
executor(resolve.bind(this), reject.bind(this))
} else {
throw new Error('executor must be function!!!')
}
}
then(onFulfilled, onRejected) {
const { state, result } = this
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
onRejected = typeof onRejected === 'function' ? onRejected : v => v
if (state === FULFILLED) {
return new Promise(resolve => queueMicrotask(() => resolve(onFulfilled(result))))
} else if (state === PENDING) {
return new Promise(resolve => this.onSuccesss.push(res => queueMicrotask(() => resolve(onFulfilled(res)))))
}
}
static resolve(value) {
return new Promise(resolve => resolve(value))
}
}
global.MyPromise = Promise
})(window)