关于Promise是什么,不做赘述。
属性
首先一个Promise类,要有如下属性:
- status: pending resolved/fulfilled rejected
- result
实例方法
- then 返回一个promise实例,参数是两个回调函数,当状态转变为resolved时,执行第一个回调函数,当状态转变为rejected时,执行第二个回调函数
- catch 传入一个回调函数,相当于then方法传入的第二个参数
- finally
静态方法
- all
- race
实现
首先我们看一下Promise是怎么使用的
new Promise((resolve, reject) => {
setTimeout(() => resolve, 100)
})
可以看出Promise对象在创建实例时就要执行传入其构造函数的方法A,维护实例的状态,并且要重新封装resolve和reject方法,替代A,以便第一时间获取状态更新。
构造函数
function MyPromise(executor) {
this.status = 'pending'
this.result = null
const resolve = (data) => {
if (this.status !== 'pending') {
return
}
this.state = 'resolved'
this.result = data
while (this.onResolvedCallbacks.length > 0) {
this.onResolvedCallbacks.shift()()
this.onRejectedCallbacks.shift()
}
}
const reject = (data) => {
if (this.status !== 'pending') return
this.status = 'rejected'
this.result = data
while (this.onRejectedCallbacks.length > 0) {
this.onResolvedCallbacks.shift()
this.onRejectedCallbacks.shift()()
}
}
executor(resolve, reject)
}
then
MyPromise.prototype.then = function (onResolved, onRejected) {
// 如果传入参数不是函数,为其初始化为空函数
onResolved = typeof onResolved === 'function' ? onResolved : ()=>{}
onRejected = typeof onRejected === 'function' ? onRejected : ()=>{}
return new MyPromise((resolve, reject) => {
// this指向执行then方法的MyPromise实例
if(this.status === 'resolved') {
let res = onResolved(this.result) // then方法的返回值
resolve(res) // 传递给下一个then
}
if(this.status === 'rejected' && onRejected) {
let err = onRejected(this.result)
reject(err)
}
// 说明前一步还没有完成,先保存两个回调,等待完成后再执行
if(this.status === 'pending') {
this.onResolvedCallbacks.push(()=>{
let res = onResolved(this.result)
resolve(res)
})
this.onRejectedCallbacks.push(()=>{
let err = onRejected(this.result)
reject(err)
})
}
})
}
catch
MyPromise.prototype.catch = function (onRejected) {
if (this.status === 'rejected') {
onRejected(this.result)
}
if (this.status === 'pending') {
this.onResolvedCallbacks.push(() => {})
this.onRejectedCallbacks.push(() => {
onRejected(ths.result)
})
}
}
all
MyPromise.prototype.all = function (promiseArrary) {
const values = []
let count = 0
return new MyPromise((resolve, reject) => {
promiseArray.forEach((p, index) => {
p = p instanceof MyPromise ? p : new MyPromise((resolve, reject) => resolve(p))
p.then(
(value) => {
count++
values[index] = value
if (count === promiseArray.length) {
resolve(values)
}
},
(err) => reject(error)
)
})
})
}
race
MyPromise.prototype.race = function(promiseArray) {
return new Promise((resolve, reject) => {
promiseArray.forEach((p, index) => {
p = p instanceof Promise ? p : new Promise((resolve, reject) => resolve(p))
p.then(value => {
resolve(value)
}, err => reject(err))
})
})
}