跳到主要内容

手写 Promise

实现 promise 常用方法

  • 初始化 & 异步调用
  • then catch 链式调用
  • 实现 API: .resolve .reject .all .race

代码实现 MyPromise

class MyPromise {
state = 'pending' //状态 pending,fulfilled,rejected
value = undefined // 成功后的值
reason = undefined // 失败后的原因

resolveCallbacks = [] // pending 下,存储成功的回调
rejectCallbacks = [] // pending 下,存储失败的回调

constructor(fn) {
const resolveHandler = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
// 状态变化后,函数执行
this.resolveCallbacks.forEach(fn => fn(this.value))
}
}

const rejectHandler = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
// 状态变化后,函数执行
this.rejectCallbacks.forEach(fn => fn(this.reason))
}
}

try {
fn(resolveHandler, rejectHandler)
} catch (err) {
resolveHandler(err)
}
}

then(fn1, fn2) {
// 当 pending 下,fn1,fn2 存储到 callbacks 中
fn1 = typeof fn1 === 'function' ? fn1 : (v) => v
fn2 = typeof fn2 === 'function' ? fn2 : (e) => e

// 函数还没执行,返回新的 promise
if (this.state === 'pending') {
const p1 = new MyPromise((resolve, reject) => {
this.resolveCallbacks.push(() => {
try {
const newValue = fn1(this.value)
resolve(newValue)
} catch (err) {
reject(err)
}
})
this.rejectCallbacks.push(() => {
try {
const newReason = fn1(this.reason)
reject(newReason)
} catch (err) {
reject(err)
}
})
})
return p1
}

// fn1 函数执行,返回新的 promise
if (this.state === 'fulfilled') {
const p1 = new MyPromise((resolve, reject) => {
try {
const newValue = fn1(this.value)
resolve(newValue)
} catch (err) {
reject(err)
}
})
return p1
}

// fn2 函数执行,返回新的 promise
if (this.state === 'rejected') {
const p1 = new MyPromise((resolve, reject) => {
try {
const newReason = fn2(this.reason)
reject(newReason)
} catch (err) {
reject(err)
}
})
return p1
}
}

// catch 就是 then 的一个语法糖,简单模式
catch(fn) {
return this.then(null, fn)
}
}

// 全局静态方法
MyPromise.resolve = function (value) {
return new MyPromise((resolve, reject) => resolve(value))
}

MyPromise.reject = function (reason) {
return new MyPromise((resolve, reject) => reject(reason))
}

MyPromise.all = function (promiseList = []) {
const p1 = new MyPromise((resolve, reject) => {
const result = [] // 存储 promiseList 所有的结果
const length = promiseList.length
let resolvedCount = 0

promiseList.forEach(p => {
p.then(data => {
result.push(data)

// resolvedCount 必须在 then 里面做 ++
// 不能使用 foreach 的 index,因为 index 是同步的
resolvedCount++
if (resolvedCount == length) {
// 已经到最后一个
resolve(result)
}
}).catch(err => {
reject(err)
})
})
})
return p1
}

MyPromise.race = function (promiseList = []) {
let resolved = false // 标记
const p1 = new MyPromise((resolve, reject) => {
promiseList.forEach(p => {
p.then(data => {
if (!resolved) {
resolve(data)
resolved = true
}
}).catch(err => {
reject(err)
})
})
})
return p1
}

测试代码

// 普通调用
const p1 = new MyPromise((resolve, reject) => {
// resolve(100)
// reject('错误...')
setTimeout(() => {
resolve(100)
}, 1000)
})

// 链式调用
const p11 = p1.then(data1 => {
console.log('data1', data1) // data1 100
return data1 + 1
})
const p12 = p11.then(data2 => {
console.log('data2', data2) // data2 101
return data2 + 1
})
const p13 = p12.catch(err => console.error(err))

// api 调用
const p2 = MyPromise.resolve(200)
const p3 = MyPromise.resolve(300)
const p4 = MyPromise.reject('错误...')
// 传入 promise 数组,等待所有的都 fulfilled 后,返回新的 promise 包含前面所有的结果
const p5 = MyPromise.all([p1, p2, p3])
p5.then(result => console.log('all result', result)) // all result (3)[200, 300, 100]
// 传入 promise 数组,只要有一个 fulfilled 即可返回
const p6 = MyPromise.race([p1, p2, p3])
p6.then(result => console.log('race result', result)) // race result 200