Promise
Promise copied to clipboard
关于 myPromiseFully.js 中的一些问题
谢谢你的文章,受益匪浅😁。以下是我发现的一些问题:
[1] Promise.all
根据 mdn 文档,Promise.all() 方法接收一个 promise 的 iterable 类型。
用 Array.isArray
来判断感觉不是很对,用 iterable?.[Symbol.iterator] == null
或许会更合适一些。
在这个基础上,使用 length 来判断迭代的个数就会出现错误了。Set 跟 Map 是没有 length 属性的。 且也不能用 forEach 来遍历,因为如果传入 string 类型会报错。
这样写的话应该好一些:
Promise.all = function (iterable) {
if (iterable?.[Symbol.iterator] == null) {
throw new TypeError(
`${iterable} is not iterable (cannot read property Symbol(Symbol.iterator))`,
)
}
return new Promise((resolve, reject) => {
let index = 0
let count = 0
const result = []
const length =
(iterable instanceof Set || iterable instanceof Map) ? iterable.size : iterable.length
if (length === 0) {
resolve([])
}
for (const item of iterable) {
if (item instanceof Promise) {
;(index => {
Promise.resolve(item).then(
value => {
result[index] = value
count += 1
count === length && resolve(result)
},
reason => {
reject(reason)
},
)
})(index)
} else {
result[index] = item
count += 1
count === length && resolve(result)
}
index += 1
}
})
}
同理,接收可迭代对象的 promise 方法都应该改一下参数校验的方式。
[2] Promise.resolve
当传入包含 then 方法的对象时,执行的顺序可能会与原生的 promise 有区别。比如
console.log(
Promise.resolve({
then() {
console.log(1)
},
}),
)
以上代码,原生 promise 会先打印 promise,再打印 1,而手写的会先打印 1,再打印 promise。
且应该先判断 then 方法是否为一个函数。如果不是的话,会返回整个对象。
[3] Promise.any
errors.push(reason);
会导致 errors 数组的顺序不可控,与原生的 Promise.any 方法有出入。
能解答下为何手写的符合规范的为何会和原生的不同么
new Promise((r)=> { console.log(0) r(); }).then(r=> { console.log(1) return new Promise((r)=> { r(); }) }).then(r=> { console.log(2) }).then(r=> { console.log(3) })
new Promise((r)=> { console.log("zero") r() }).then(r=> { console.log('one'); }).then(r=> { console.log('two'); }).then(r=> { console.log('three'); })
// 原生的promise输出如下 0 zero 1 one two three 2 3
// 您写的输出如下 0 zero 1 one two 2 three 3