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