Promise 静态方法实现
分类:javascript
原文地址
概述
6 个静态方法的一些注意点罗列如下:
- 除了
resolve
reject
其它静态方法的参数都要求传递一个可迭代对象(iterable),而可迭代对象具有 Symbol.iterator 属性定义生成器(执行生成器生成迭代器),通过判断实参 Symbol.iterator 是否为函数作防御性检测 try...catch
把未传参数或者传undefined
错误信息通过 reject 传递出去- 静态方法都返回 promise,所以基本思路是返回一个 Promise 实例,再根据接口的各自用途实现内部逻辑
- iterable 对象中每一项同时执行(当然还是顺序执行,但不必等待其它项的执行结果)
- 由于 iterable 对象中的每一项不必是 Promise 实例,那么使用 Promise.resolve 包一下强制生成 Promise 实例
- 多条 promise 链,同样位置的回调同属一个微任务队列,链条后面同样位置的回调同属于后面的微任务队列,如下:
Promise.reject(1).catch(r=>console.log(r))
Promise.reject(2).then(r=>console.log(r)).catch(e=>console.log('e',e))
Promise.resolve(3).then(r=>console.log(r)).then(_=>console.log('then'))
// 1
// 3
// e 2
// then
Promise.resolve
快速生成一个 fulfilled promise 对象
Promise._resolve = value => new Promise(resolve => resolve(value))
Promise.reject
快速生成一个 rejected promise 对象
Promise._reject = value => new Promise((_, reject) => reject(value))
Promise.all
iterable 对象只要有一项的状态是 rejected 返回的 promise 状态为 rejected,否则为 fulfilled,fulfilled 的数组每一项顺序与实参一致
Promise._all = (array) => {
return new Promise((resolve, reject) => {
try {
if (typeof array[Symbol.iterator] !== 'function')
return reject(
new TypeError(
`${typeof array} ${array} is not iterable (cannot read property Symbol(Symbol.iterator))`
)
)
array = [...array[Symbol.iterator]()]
const result = []
let length = array.length
array.forEach((item, i) =>
Promise.resolve(item).then((data) => {
result[i] = data
--length === 0 && resolve(result)
}, reject)
)
} catch (e) {
reject(e)
}
})
}
Promise.allSettled
返回的 promise 状态一定 fulfilled,其中每一项的状态与数据通过传递给成功回调的对象描述,结构为 [{status: 'fulfilled', value: 1}, {status: 'rejected', reason: 'something went wrong']
,顺序与实参一致
Promise._allSettled = (array) => {
return new Promise((resolve, reject) => {
try {
if (typeof array[Symbol.iterator] !== 'function')
reject(
new TypeError(
`${typeof array} ${array} is not iterable (cannot read property Symbol(Symbol.iterator))`
)
)
array = [...array[Symbol.iterator]()]
const result = []
let length = array.length
array.forEach((item, i) =>
Promise.resolve(item).then(
(value) => {
result[i] = {
status: 'fulfilled',
value,
}
--length === 0 && resolve(result)
},
(e) => {
result[i] = {
status: 'rejected',
reason: e,
}
--length === 0 && resolve(result)
}
)
)
} catch (e) {
reject(e)
}
})
}
Promise.any
与 Promise.all
相反,只要有一项状态为 fulfilled 返回 promise 状态为 fulfilled,否则为 rejected
Promise._any = (array) => {
return new Promise((resolve, reject) => {
try {
if (typeof array[Symbol.iterator] !== 'function')
reject(
new TypeError(
`${typeof array} ${array} is not iterable (cannot read property Symbol(Symbol.iterator))`
)
)
array = [...array[Symbol.iterator]()]
const result = []
let length = array.length
array.forEach((item, i) =>
Promise.resolve(item).then(resolve, (e) => {
--length === 0 &&
reject(`AggretatedError: All promises were rejected`)
})
)
} catch (e) {
reject(e)
}
})
}
Promise.race
竞态,iterable 对象中状态先从 pending 转出的那一项成为返回 promise 的状态,并且把数据传递给成功/失败回调
Promise._race = (array) => {
return new Promise((resolve, reject) => {
try {
if (typeof array[Symbol.iterator] !== 'function')
reject(
new TypeError(
`${typeof array} ${array} is not iterable (cannot read property Symbol(Symbol.iterator))`
)
)
array = [...array[Symbol.iterator]()]
array.forEach((item) => Promise.resolve(item).then(resolve, reject))
} catch (e) {
reject(e)
}
})
}