前言
经过上一篇的学习,你肯定已经会了 Promise 的基本使用!# 细嚼慢咽(一)!适合初学者的 Promise 基础教程指南!年前的饺子得吃!那么接下来,就跟着我,手撕 Promise 方法,掌握运行的原理!吊打面试官!
resolve()
我们知道 resolve(params) 方法会把 params 传给下一次 then(val) 中的 val。
而 params 又有三种情况:
- 普通的值,如 string、number、boolean
- Promise 对象
- 实现了 thenabale 方法的 JS 对象
而 resolve(params) 方法运行的原理就是:
- 如果 params 是普通的值或实现了 thenabale 方法的 JS 对象,则调用 Promise.resolve(params) 将 params 包裹成 Promise 并返回这个 Promise 对象
- 如果 params 是 Promise,则直接返回即可
比如下面的例子:
//例子:
new Promise((resolve, reject) => {
resolve('大家好,我是玺子哥!')
}).then(val => {
console.log(val)
})
//输出:
大家好,我是玺子哥!
手写实现如下:
function myResolve(params) {
//如果 params 是 Promise,则直接返回
if (params instanceof Promise) return params
//否则,将 params 包裹成 Promise,返回这个 Promise 对象
return Promise.resolve(params)
}
运行结果如下:
all()
all(promiseArr) 是接受一组 promise 对象作为参数,根据下面两种情况,返回结果
- 如果 promiseArr 里面的每一个 promise 对象都为 fulfilled,则把每一个 fulfilled 的结果添加到一个结果数组 res 中,返回 res
- 如果 promiseArr 里面有一个 promise 对象为 rejected,则把 第一个 rejected 的值返回
实现如下:
function myAll(promiseArr) {
let index = 0, res = []
//返回的新的 Promise
return new Promise((resolve, reject) => {
//遍历 promiseArr,判断每一个 promise 的状态
promiseArr.forEach(p => {
//通过 Promise.resolve(p) 判断当前 p 的状态
Promise.resolve(p).then(val => {
index++
//若为 fulfilled,则添加到 res 中
res.push(val)
//如果相等,表示所有的 promise 均为 fulfilled,返回 res
if (index === promiseArr.length) {
resolve(res)
}
}, err => {
//如果有一个 promise 为 rejected
reject(err)
})
})
})
}
运行结果如下:
- promiseArr 全是 fulfilled 时:
- promiseArr 至少有一个是 rejected 时:
race()
race() 和 all() 类似,也是收集 promise 对象的数组 promiseArr 作为参数,只不过对于 race() 来说,谁先有状态,就先用谁的结果。
实现如下:
function myRace(promiseArr) {
return new Promise((resolve, reject) => {
//遍历 promiseArr
promiseArr.forEach(p => {
Promise.resolve(p).then(val => {
//最先有结果的那个 promise 是 fulfilled
resolve(val)
}, err => {
//最先有结果的那个 promise 是 rejected
reject(err)
})
})
})
}
运行结果如下:
allSettled()
allSettled() 方法和 all() 也类似,也接受 promiseArr 数组作为参数,它的规则如下:
- 不管 promiseArr 里面的 promise 是 fulfilled 还是 rejected,都会把它的结果和状态都放进一个对象,即:{status: 'fulfilled', value: ''},然后添加到结果数组 res 中。
- 只要调用了 allSettled() 方法,原 Promise 对象的状态一定是 fulfilled
实现如下:
function myAllsettled(promiseArr) {
let res = [], index = 0;
return new Promise((resolve, reject) => {
promiseArr.forEach(p => {
Promise.resolve(p).then(val => {
res.push({
status: 'fulfilled',
val
})
index++
}, err => {
res.push({
status: 'rejected',
val: err
})
index++
}).finally(() => {
//如果相等,则遍历完毕,且原 Promise 一定是 fulfilled
if(index === promiseArr.length) resolve(res)
})
})
})
}
运行结果如下:
any()
any() 同样和前面的几个类似,也接受 promiseArr 数组作为参数,规则如下:
- promiseArr 里至少有一个为 fulfilled,则把成功的结果返回,原 Promise 对象为 fulfilled
- promiseArr 里如果全是 rejected 或者 promiseArr为空数组,则会报错AggregateError
实现如下:
function myAny(promiseArr) {
let index = 0;
return new Promise((resolve, reject) => {
promiseArr.forEach(p => {
Promise.resolve(p).then(val => {
resolve(val)
}, err => {
index++;
if(index === promiseArr.length) {
reject(new AggregateError('All promises were rejected'))
}
})
})
})
}
运行结果如下:
结尾
看到这里,恭喜你已经更进一步!
如果 这篇文章 对你有帮助,欢迎 点赞、收藏、评论,如果有 错误或还有疑问的地方,请 评论留言或者私信!