Array.fromAsync()
Базовая поддержка Широко доступно
Эта функция хорошо зарекомендовала себя и работает на множестве устройств и версий браузеров. Она доступна в браузерах с января 2024 года.
Статический метод Array.fromAsync() создает новый, мелкокопированный экземпляр Array из асинхронного итерируемого объекта, итерируемого объекта или массивоподобного объекта.
Синтаксис
Array.fromAsync(items) Array.fromAsync(items, mapFn) Array.fromAsync(items, mapFn, thisArg)
Параметры
-
items - Асинхронный итерируемый, итерируемый или массивоподобный объект для преобразования в массив.
-
mapFnНеобязательный - Функция, которая будет вызвана для каждого элемента массива. Если предоставлена, каждое значение, добавляемое в массив, сначала проходит через эту функцию, и возвращаемое значение
mapFnдобавляется в массив вместо него (после ожидания). Функция вызывается со следующими аргументами:-
element - Текущий элемент, обрабатываемый в массиве. Если
itemsявляется синхронным итерируемым или массивоподобным объектом, то все элементы сначала ожидаются, иelementникогда не будет thenable. Еслиitemsявляется асинхронным итерируемым объектом, то каждое возвращаемое значение передается как есть. -
index - Индекс текущего элемента, обрабатываемого в массиве.
-
-
thisArgНеобязательный - Значение, которое будет использоваться как
thisпри выполненииmapFn.
Возвращаемое значение
Новый Promise, значение которого при выполнении является новым экземпляром Array.
Описание
Array.fromAsync() позволяет создавать массивы из:
-
асинхронных итерируемых объектов (таких как
ReadableStreamиAsyncGenerator); или, если объект не является асинхронным итерируемым, -
итерируемых объектов (таких как
MapиSet); или, если объект не является итерируемым, - массивоподобных объектов (объектов с свойством
lengthи индексированными элементами).
Array.fromAsync() итерирует асинхронный итерируемый объект способом, очень похожим на for await...of. Array.fromAsync(items) в целом эквивалентен следующему коду, если items является асинхронным или синхронным итерируемым объектом:
const result = [];
for await (const element of items) {
result.push(element);
}
Array.fromAsync() почти эквивалентен Array.from() по поведению, за исключением следующего:
-
Array.fromAsync()обрабатывает асинхронные итерируемые объекты. -
Array.fromAsync()возвращаетPromise, который выполняется до экземпляра массива. - Если
Array.fromAsync()вызывается с неасинхронным итерируемым объектом, каждый элемент, добавляемый в массив, сначала ожидается. - Если предоставлен
mapFn, его выходные данные также внутренне ожидаются.
Array.fromAsync() и Promise.all() могут преобразовывать итерируемый объект промисов в промис массива. Однако есть два ключевых отличия:
-
Array.fromAsync()последовательно ожидает каждое значение, возвращаемое объектом.Promise.all()одновременно ожидает все значения. -
Array.fromAsync()лениво итерирует итерируемый объект и не получает следующее значение, пока текущее не будет разрешено.Promise.all()получает все значения заранее и ожидает их всех.
Примеры
Массив из асинхронного итерируемого объекта
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]
Когда items является асинхронным итерируемым объектом, где value каждого результата также является промисом, то эти промисы добавляются в результирующий массив без ожидания. Это соответствует поведению for await...of.
function createAsyncIter() {
let i = 0;
return {
[Symbol.asyncIterator]() {
return {
async next() {
if (i > 2) return { done: true };
i++;
return { value: Promise.resolve(i), done: false };
},
};
},
};
}
Array.fromAsync(createAsyncIter()).then((array) => console.log(array));
// (3) [Promise, Promise, Promise]
Примечание: На практике вы редко столкнетесь с асинхронным итерируемым объектом, который возвращает промисы, потому что если вы реализуете его с помощью функции асинхронного генератора, то выражение yield автоматически распаковывает промисы.
Массив из синхронного итерируемого объекта
Array.fromAsync(
new Map([
[1, 2],
[3, 4],
]),
).then((array) => console.log(array));
// [[1, 2], [3, 4]]
Массив из синхронного итерируемого объекта, возвращающего промисы
Array.fromAsync( new Set([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]), ).then((array) => console.log(array)); // [1, 2, 3]
Массив из массивоподобного объекта промисов
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 с синхронным итерируемым объектом
Когда items является синхронным итерируемым или массивоподобным объектом, как входные, так и выходные данные mapFn внутренне ожидаются 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]
Использование mapFn с асинхронным итерируемым объектом
Когда items является асинхронным итерируемым объектом, входные данные для mapFn не ожидаются, а выходные данные ожидаются. Используя ту же функцию createAsyncIter, что и выше:
Array.fromAsync(createAsyncIter(), async (element) => (await element) * 2).then( (array) => console.log(array), ); // [2, 4, 6]
Любопытно, что это означает, что Array.fromAsync(createAsyncIter()) не эквивалентен Array.fromAsync(createAsyncIter(), (element) => element), потому что последний ожидает каждое возвращаемое значение, а первый — нет.
Array.fromAsync(createAsyncIter(), (element) => element).then((array) => console.log(array), ); // [1, 2, 3]
Сравнение с Promise.all()
Array.fromAsync() последовательно ожидает каждое значение, возвращаемое объектом. Promise.all() одновременно ожидает все значения.
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() базового итератора будет вызван, если он существует, чтобы позволить итератору выполнить очистку.
function* generatorWithRejectedPromises() {
try {
yield 0;
yield Promise.reject(new Error("error"));
} finally {
console.log("called finally");
}
}
(async () => {
try {
await Array.fromAsync(generatorWithRejectedPromises());
} catch (e) {
console.log("caught", e);
}
})();
// called finally
// caught Error: error
Спецификации
Совместимость с браузерами
| Desktop | Mobile | Server | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on iOS | Samsung Internet | WebView Android | WebView on iOS | Bun | Deno | Node.js | |
fromAsync |
121 |
121 |
115 |
107 |
16.4 |
121 |
115 |
81 |
16.4 |
25.0 |
121 |
16.4 |
1.0.0 |
1.38 |
22.0.0 |
См. также
- Polyfill для
Array.fromAsyncвcore-js - Руководство по индексированным коллекциям
ArrayArray()Array.of()Array.from()for await...of
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fromAsync