前言
promise相关问题是很常见的面试题了,最近也在熟悉相关的东西所以趁着这个机会顺便总结一下,写的不好和不对的地方大家多多指教。
什么是promise
Promise对象用于表示一个异步操作的最终完成(或失败)及其结果值。
简易描述
- promise是一个类,它的构造函数接受一个函数,函数的两个参数也是函数;
- promise拥有三个状态,pending、fulfilled,rejected,默认是pending状态,成功执行resolve表示,失败执行reject回调,状态一旦更改就不能再次更改;
- 存在一个实例方法then,一个参数是成功之后执行的回调函数,一个参数是失败执行的回调函数;
- then支持链式调用。
实现
class MyPromise {
static PENDING = 'pending'
static FULFILLED = 'fulfilled'
static REJECTED = 'rejected'
constructor(executor) {
this.status = MyPromise.PENDING // 默认pending态
this.value = undefined // 执行成功的值
this.reason = undefined // 执行失败的值
this.successAry = []
this.failAry = []
executor(this._resolve.bind(this), this._reject.bind(this))
}
_resolve (value) {
// promise状态一旦更改就不能再更改了
if (this.status === MyPromise.PENDING) {
this.status = MyPromise.FULFILLED
this.value = value
this.successAry.forEach(cb => cb(this.value))
}
}
_reject (reason) {
if (this.status === MyPromise.REJECTED) {
this.status = MyPromise.REJECTED
this.reason = reason
this.failAry.forEach(cb => cb(this.reason))
}
}
_then (onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function'
? onFulfilled : value => value // .then的回调函数,不是函数的话自己生成一个
onRejected = typeof onRejected === 'function'
? onRejected : reason => reason
return new MyPromise((nextResolve, nextReject) => {
if (this.status === MyPromise.FULFILLED) {
let value = onFulfilled(this.value) // 计算出下一个回调的返回值
nextResolve(value)
}
if (this.status === MyPromise.REJECTED) {
let reason = onRejected(this.reason)
nextReject && nextReject(reason) // 因为第二个参数大部分时候不传,所以要做一下兼容
}
// 考虑到透传的情况,比如 let pr = Promise().resolve(2) pr.then().then(res => {xxxxxxxxxxxxx})
if (this.status === MyPromise.PENDING) {
this.successAry.push(value => {
let success_value = onfulfilled(value)
nextResolve(success_value)
})
this.failAry.push(reason => {
let fail_reason = onRejected(reason)
nextReject && nextReject(fail_reason)
})
}
})
}
_catch(onRejected) {
return this._then(undefined, onRejected)
}
finally (fn) {
return this._then(fn, fn)
}
}
测试
我们可以看到基本成型了,那么接下来再实现一下它的其他方法
其他方法
- resolve 其实就是return出一个MyPromise的fulfilled状态
static resolve(value) {
return new MyPromise((resolve, reject) => {resolve(value)})
}
- reject 其实就是return出一个MyPromise的rejected状态
static reject(reason) {
return new MyPromise((resolve, reject) => {reject(reason)})
}
- all 传入一个数组,只有数组内的状态变成fulfilled状态才会返回所有的结果,如果有一个rejected状态,返回错误信息
static all(promises) {
return new MyPromise((resolve, reject) => {
if(!Array.isArray(promises)) throw new Error('参数必须是一个数组')
let result = [], count = 0
for (let i = 0; i < promises.length; i++) {
MyPromise.resolve(promises[i])._then(res => {
result.push(res)
if (++count === promises.length) resolve(result)
})._catch(reason => { reject(reason) })
}
})
}
- race 和all类似,只要其中一个实例状态改变,就返回那个实例状态的返回值
static race(promises) {
return new MyPromise((resolve, reject) => {
if(!Array.isArray(promises)) throw new Error('参数必须是一个数组')
for (let i = 0; i < promises.length; i++) {
MyPromise.resolve(promises[i])._then(res => {
resolve(res)
})._catch(err => { reject(err) })
}
})
}
- allSelected
只有等到所有这些参数实例都返回结果,不管是
fulfilled还是rejected,而且该方法的状态只可能变成fulfilled。此方法与Promise.all的区别是all无法确定所有请求都结束,因为在all中,如果有一个被Promise被rejected,p的状态就立马变成rejected,有可能有些异步请求还没走完。
static allSelected (promises) {
return new MyPromise((resolve, reject) => {
let result = [], count = 0
for (let i = 0; i < promises.length; i++) {
MyPromise.resolve(promises[i]).finally(res => {
result.push(res)
++count === promises.length && resolve(result)
})
}
})
}
结语
写的不好,有错误的地方还请各位大佬多多指教,感恩家人🙏