Promise基本使用
const p = new Promise((resolve, reject) => {
resolve('ok')
reject('error')
})
p.then(res => {
console.log(res)
}, err => {
console.log(err)
})
- Promise接收一个函数,这个函数会立即执行
- Promise状态不可逆
- pending
- fulfilled
- rejected
- 结果是resolve生效,忽略reject
基础实现
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class myPromise{
constructor(executor) {
this.status = 'pending' // 保存当前处于哪一状态
this.reason = undefined // 保存reject结果
this.value = undefined // 保存resolve结果
const resolve = (value) => {
console.log(value)
this.value = value
}
const reject = (reason) => {
console.log(reason)
this.reason = reason
}
executor(resolve, reject)
}
}
const p = new myPromise((resolve, reject) => {
resolve('success')
reject('fail')
throw new Error('error')
})
问题:
- resolve和reject都执行了
- 最终status: rejected
- 无法捕获主体异常
添加状态不可逆
const resolve = (value) => {
if(this.status === PENDING) {
this.status = FULFILLED
console.log(value)
this.value = value
}
}
const reject = (reason) => {
if(this.status === PENDING) {
this.status = REJECTED
console.log(reason)
this.reason = reason
}
}
捕获主体异常
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
实现then
then(onFulfilled, onRejected) {
if(this.status === FULFILLED) {
onFulfilled(this.value)
}
if(this.status === REJECTED) {
onFulfilled(this.reason)
}
}
// 测试
p.then(res => {
console.log(res) // success
})
问题:
无法处理主体异步问题
const p = new myPromise((resolve, reject) => {
setTimeout(() => {
resolve('timeout')
}, 1000)
})
p.then(res => {
console.log('res', res) // 这里不会执行
})
解决异步问题
因为执行then的时候status的状态还是pending,所以就没办法执行onFulfilled, 可以先将then的回调先保存起来,在resolve或reject时再调用
constructor(executor) {
this.fulfilledCallbacks = [] // then 可以多次调用,使用数组保存
this.rejectedCallbacks = []
}
then(onFulfilled, onRejected) {
if(this.status === PENDING) {
onFulfilled && this.fulfilledCallbacks.push(onFulfilled)
onRejected && this.rejectedCallbacks.push(onRejected)
}
}
const resolve = (value) => {
this.fulfilledCallbacks.forEach(cb => {
cb(this.value)
})
}
const reject = (reason) => {
this.fulfilledCallbacks.forEach(cb => {
cb(this.reason)
})
}
完整代码
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class myPromise{
constructor(executor) {
this.status = 'pending' // 保存当前处于哪一状态
this.reason = undefined // 保存reject结果
this.value = undefined // 保存resolve结果
this.fulfilledCallbacks = []
this.rejectedCallbacks = []
const resolve = (value) => {
if(this.status === PENDING) {
this.status = FULFILLED
// console.log(value)
this.value = value
this.fulfilledCallbacks.forEach(cb => {
cb(this.value)
})
}
}
const reject = (reason) => {
if(this.status === PENDING) {
this.status = REJECTED
// console.log(reason)
this.reason = reason
this.rejectedCallbacks.forEach(cb => {
cb(this.reason)
})
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected) {
if(this.status === FULFILLED) {
onFulfilled(this.value)
}
if(this.status === REJECTED) {
onFulfilled(this.reason)
}
if(this.status === PENDING) {
onFulfilled && this.fulfilledCallbacks.push(onFulfilled)
onRejected && this.rejectedCallbacks.push(onRejected)
}
}
}
const p = new myPromise((resolve, reject) => {
// resolve('success')
// reject('fail')
// throw new Error('eeeeee')
setTimeout(() => {
resolve('timeout')
}, 1000)
})
p.then(res => {
console.log('res1==========================', res)
})
p.then(res => {
console.log('res2==========================', res)
})
实现链式调用
其实就是返回一个新的promise实例
then(onFulfilled, onRejected) {
const thenPromise = new myPromise((resolve, reject) => {
if(this.status === FULFILLED) {
try {
const value = onFulfilled(this.value)
resolve(value)
} catch (error) {
reject(error)
}
}
if(this.status === REJECTED) {
try {
const value = onRejected(this.reason)
resolve(value)
} catch (error) {
reject(error)
}
}
if(this.status === PENDING) {
onFulfilled && this.fulfilledCallbacks.push(() => {
try {
const value = onFulfilled(this.value)
resolve(value)
} catch (error) {
reject(error)
}
})
onRejected && this.rejectedCallbacks.push(() => {
try {
const value = onRejected(this.reason)
resolve(value)
} catch (error) {
reject(value)
}
})
}
})
return thenPromise
}
注意之前的
onFulfilled && this.fulfilledCallbacks.push(onFulfilled)
要改成下面这样
onFulfilled && this.fulfilledCallbacks.push(() => {
try {
const value = onFulfilled(this.value)
resolve(value)
} catch (error) {
reject(error)
}
})
因为之前是直接push了onFulfilled,无法拿到onFulfilled的结果
添加catch
catch可以看做是then只传了第二个参数
catch(onRejected) {
this.then(undefined, onRejected)
}
- 完整代码
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
// 统一处理异常
const catchFn = (fn, value, resolve, reject) => {
try {
const result = fn(value)
resolve(result)
} catch (error) {
reject(error)
}
}
class myPromise{
constructor(executor) {
this.status = 'pending' // 保存当前处于哪一状态
this.value = undefined // 保存resolve结果
this.reason = undefined // 保存reject结果
this.fulfilledCallbacks = []
this.rejectedCallbacks = []
const resolve = (value) => {
if(this.status === PENDING) {
this.status = FULFILLED
// console.log(value)
this.value = value
while(this.fulfilledCallbacks.length) {
this.fulfilledCallbacks.shift()(this.value)
}
}
}
const reject = (reason) => {
if(this.status === PENDING) {
this.status = REJECTED
// console.log(reason)
this.reason = reason
while(this.rejectedCallbacks.length) {
this.rejectedCallbacks.shift()(this.reason)
}
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected) {
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
const thenPromise = new myPromise((resolve, reject) => {
if(this.status === FULFILLED) {
catchFn(onFulfilled, this.value, resolve, reject)
}
if(this.status === REJECTED) {
catchFn(onRejected, this.reason, resolve, reject)
}
if(this.status === PENDING) {
onFulfilled && this.fulfilledCallbacks.push(() => {
catchFn(onFulfilled, this.value, resolve, reject)
})
onRejected && this.rejectedCallbacks.push(() => {
catchFn(onRejected, this.reason, resolve, reject)
})
}
})
return thenPromise
}
catch(onRejected) {
this.then(undefined, onRejected)
}
}