写这篇文章的初衷
在整理promise知识点的过程中,想到之前去外面面试的小伙伴经常会说面试官要求现场写一个promise类,在掘金上没有看到一个简单明了的源码实现,刚好最近刚学习完继承与原型链相关知识,趁热打铁试试手撕promise功能。
class MyPromise {
static PENDING = 'pending'
static FULFILLED = 'fulfilled'
static REJECT = 'reject'
constructor(executor) {
this.status = MyPromise.PENDING
this.value = undefined
this.callbacks = [] // 存放需要回调的函数
// 捕获实例化传入方法在执行时出现错误异常
try {
// resolve方法没有this指向,需要传入this指向。
executor(this.resolve.bind(this), this.reject.bind(this))
} catch (error) {
this.reject(error)
}
}
resolve (value) {
if (this.status === MyPromise.PENDING) {
this.status = MyPromise.FULFILLED
this.value = value
// 实现then中的回调是异步执行
setTimeout(() => {
this.callbacks.map(item => {
item.onFulfilled(value)
})
})
}
}
reject (reason) {
if (this.status === MyPromise.PENDING) {
this.status = MyPromise.REJECT
this.value = reason
// 实现then中的回调是异步执行
setTimeout(() => {
this.callbacks.map(item => {
item.onRejected(reason)
})
})
}
}
then (onFulfilled, onRejected) {
// 解决传入的不为function
if (typeof onFulfilled !== 'function') {
// 解决then()不传值时的穿透传递问题
onFulfilled = (value)=> value
}
if (typeof onRejected !== 'function') {
onRejected = (reason)=> {throw reason}
}
// 返回一个新的promise解决链式调用
let myPromise = new MyPromise((resolve, reject) => {
// 解决resolve与reject被放在异步方法进行操作
if (this.status === MyPromise.PENDING) {
this.callbacks.push({
onFulfilled: value => {
this.parse(myPromise, onFulfilled, value, resolve, reject)
},
onRejected: value => {
this.parse(myPromise, onRejected, value, resolve, reject)
},
})
}
if (this.status === MyPromise.FULFILLED) {
// then的回调函数都是异步的,所以使用setTimeout放在异步队列里
setTimeout(() => {
this.parse(myPromise, onFulfilled, this.value, resolve, reject)
})
}
if (this.status === MyPromise.REJECT) {
setTimeout(() => {
this.parse(myPromise, onRejected, this.value, resolve, reject)
})
}
})
return myPromise
}
catch (onRejected) {
return this.then(null, onRejected)
}
/**
* 处理过程公共代码提取
* @param {*} myPromise 新promise
* @param {*} callback 回调函数
* @param {*} value 返回数值
* @param {*} resolve 成功函数
* @param {*} reject 失败函数
*/
parse (myPromise, callback, value, resolve, reject) {
// 捕获reject状态下的then()穿透
try {
var result = callback(value) // var起到跨越块级作用域
} catch (error) {
reject(error)
}
// 限制return返回自身
if (myPromise === result) {
throw TypeError('Chaining cycle detected for promise')
}
// 解决方法在调用时出现错误异常
try {
// return 返回的是一个promise,此时只需要获取内部的值即可
if (result instanceof MyPromise) {
result.then(resolve,reject)
} else {
// return出来的值一定由新promise的resolve进行接收
resolve(result)
}
} catch (error) {
// 错误异常的结果一定由新promise的reject进行接收
reject(error)
}
}
static resolve (value) {
return new MyPromise((resolve, reject) => {
try {
// return 返回的是一个promise,此时只需要获取内部的值即可
if (value instanceof MyPromise) {
value.then(resolve,reject)
} else {
// return出来的值一定由新promise的resolve进行接收
resolve(value)
}
} catch (error) {
// 错误异常的结果一定由新promise的reject进行接收
reject(error)
}
})
}
static reject (value) {
return new MyPromise((resolve, reject) => {
reject(value)
})
}
static all(promises) {
const values = []
return new MyPromise((resolve, reject) => {
promises.forEach((promise,index) => {
promise.then(
value => {
values[index] = value
if(values.length === promises.length) {
resolve(values)
}
},
reason => {
reject(reason)
}
)
})
})
}
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
promise.then(
value => {
resolve(value)
},
reason => {
reject(reason)
}
)
})
})
}
}