Array.fromAsync()
Baseline 2024
Newly available
Since January 2024, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.
Array.fromAsync() 静态方法从 异步可迭代、iterable 或 array-like 对象创建新的浅复制 Array 实例。
¥The Array.fromAsync() static method creates a new, shallow-copied Array instance from an async iterable, iterable, or array-like object.
语法
参数
返回值
描述
¥Description
Array.fromAsync() 允许你从以下位置创建数组:
¥Array.fromAsync() lets you create arrays from:
- 异步可迭代对象(
ReadableStream和AsyncGenerator等对象);或者,如果对象不是异步可迭代的, - 可迭代对象(
Map和Set等对象);或者,如果该对象不可迭代, - 类似数组的对象(具有
length属性和索引元素的对象)。
Array.fromAsync() 以与 for await...of 非常相似的方式迭代异步可迭代。Array.fromAsync() 在行为方面几乎等同于 Array.from(),但以下内容除外:
¥Array.fromAsync() iterates the async iterable in a fashion very similar to for await...of. Array.fromAsync() is almost equivalent to Array.from() in terms of behavior, except the following:
Array.fromAsync()处理异步可迭代对象。Array.fromAsync()返回满足数组实例的Promise。- 如果使用非异步可迭代对象调用
Array.fromAsync(),则要添加到数组的每个元素首先是 awaited。 - 如果提供了
mapFn,则内部等待其输入和输出。
Array.fromAsync() 和 Promise.all() 都可以将可迭代的 Promise 转换为数组的 Promise。但是,有两个关键区别:
¥Array.fromAsync() and Promise.all() can both turn an iterable of promises into a promise of an array. However, there are two key differences:
Array.fromAsync()等待从对象中顺序产生的每个值。Promise.all()同时等待所有值。Array.fromAsync()延迟迭代可迭代对象,并且在当前值解决之前不会检索下一个值。Promise.all()提前检索所有值并等待它们全部。
示例
来自异步可迭代的数组
来自同步迭代的数组
来自同步迭代的数组,产生承诺
来自 Promise 的类数组对象的数组
使用 mapFn
¥Using mapFn
mapFn 的输入和输出都由 Array.fromAsync() 内部等待。
¥Both the input and output of mapFn are awaited internally by Array.fromAsync().
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() 的比较
¥Comparison with Promise.all()
Array.fromAsync() 等待从对象中顺序产生的每个值。Promise.all() 同时等待所有值。
¥Array.fromAsync() awaits each value yielded from the object sequentially. Promise.all() awaits all values concurrently.
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
})();
同步迭代没有错误处理
¥No error handling for sync iterables
与 for await...of 类似,如果正在迭代的对象是同步迭代器,并且迭代时抛出错误,则不会调用底层迭代器的 return() 方法,因此迭代器不会关闭。
¥Similar to for await...of, if the object being iterated is a sync iterable, and an error is thrown while iterating, the return() method of the underlying iterator will not be called, so the iterator is not closed.
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 循环,并自己使用 await 每个值。
¥If you need to close the iterator, you need to use a for...of loop instead, and await each value yourself.
(async () => {
const arr = [];
try {
for (const val of generatorWithRejectedPromises()) {
arr.push(await val);
}
} catch (e) {
console.log("caught", e);
}
})();
// called finally
// caught 3
规范
| Specification |
|---|
| ES Array.fromAsync (2022) # sec-array.fromAsync |
浏览器兼容性
BCD tables only load in the browser