Array.fromAsync()
语法
js
Array.fromAsync(arrayLike)
Array.fromAsync(arrayLike, mapFn)
Array.fromAsync(arrayLike, mapFn, thisArg)
参数
返回值
描述
Array.fromAsync()
允许您从以下对象创建数组:
- 异步可迭代对象(如
ReadableStream
和AsyncGenerator
这样的对象);或者,如果对象不是异步可迭代的,则 - 可迭代对象(如
Map
和Set
这样的对象);或者,如果对象不是可迭代的,则 - 类数组对象(具有
length
属性和索引元素的对象)。
Array.fromAsync()
以与 for await...of
非常相似的方式迭代异步可迭代对象。Array.fromAsync()
在行为方面几乎等效于 Array.from()
,除了以下几点:
Array.fromAsync()
处理异步可迭代对象。Array.fromAsync()
返回一个Promise
,该 Promise 完成为数组实例。- 如果
Array.fromAsync()
被调用时带有一个非异步可迭代对象,则要添加到数组的每个元素都将首先 等待。 - 如果提供
mapFn
,则其输入和输出将在内部等待。
Array.fromAsync()
和 Promise.all()
都可以将一个 Promise 的可迭代对象转换为一个数组的 Promise。但是,它们之间有两个关键区别:
Array.fromAsync()
依次等待从对象中产生的每个值。Promise.all()
并发等待所有值。Array.fromAsync()
懒惰地迭代可迭代对象,并且在当前值结算之前不会检索下一个值。Promise.all()
会提前检索所有值并等待它们全部结算。
示例
从异步可迭代对象创建数组
js
const asyncIterable = (async function* () {
for (let i = 0; i < 5; i++) {
await new Promise((resolve) => setTimeout(resolve, 10 * i));
yield i;
}
})();
Array.fromAsync(asyncIterable).then((array) => console.log(array));
// [0, 1, 2, 3, 4]
从同步可迭代对象创建数组
js
Array.fromAsync(
new Map([
[1, 2],
[3, 4],
]),
).then((array) => console.log(array));
// [[1, 2], [3, 4]]
从产生 Promise 的同步可迭代对象创建数组
js
Array.fromAsync(
new Set([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]),
).then((array) => console.log(array));
// [1, 2, 3]
从 Promise 的类数组对象创建数组
js
Array.fromAsync({
length: 3,
0: Promise.resolve(1),
1: Promise.resolve(2),
2: Promise.resolve(3),
}).then((array) => console.log(array));
// [1, 2, 3]
使用 mapFn
mapFn
的输入和输出都由 Array.fromAsync()
在内部等待。
js
function delayedValue(v) {
return new Promise((resolve) => setTimeout(() => resolve(v), 100));
}
Array.fromAsync(
[delayedValue(1), delayedValue(2), delayedValue(3)],
(element) => delayedValue(element * 2),
).then((array) => console.log(array));
// [2, 4, 6]
与 Promise.all() 的比较
Array.fromAsync()
依次等待从对象中产生的每个值。Promise.all()
并发等待所有值。
js
function* makeIterableOfPromises() {
for (let i = 0; i < 5; i++) {
yield new Promise((resolve) => setTimeout(resolve, 100));
}
}
(async () => {
console.time("Array.fromAsync() time");
await Array.fromAsync(makeIterableOfPromises());
console.timeEnd("Array.fromAsync() time");
// Array.fromAsync() time: 503.610ms
console.time("Promise.all() time");
await Promise.all(makeIterableOfPromises());
console.timeEnd("Promise.all() time");
// Promise.all() time: 101.728ms
})();
对同步可迭代对象没有错误处理
与 for await...of
类似,如果正在迭代的对象是同步可迭代对象,并且在迭代过程中抛出错误,则不会调用底层迭代器的 return()
方法,因此迭代器不会关闭。
js
function* generatorWithRejectedPromises() {
try {
yield 0;
yield Promise.reject(3);
} finally {
console.log("called finally");
}
}
(async () => {
try {
await Array.fromAsync(generatorWithRejectedPromises());
} catch (e) {
console.log("caught", e);
}
})();
// caught 3
// No "called finally" message
如果需要关闭迭代器,则需要使用 for...of
循环,并自行等待每个值。
js
(async () => {
const arr = [];
try {
for (const val of generatorWithRejectedPromises()) {
arr.push(await val);
}
} catch (e) {
console.log("caught", e);
}
})();
// called finally
// caught 3
规范
规范 |
---|
ES Array.fromAsync (2022) # sec-array.fromAsync |
浏览器兼容性
BCD 表格仅在启用 JavaScript 的浏览器中加载。