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(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
를 반환합니다.- 비동기 순회 가능 객체로
Array.fromAsync()
를 호출하면 배열에 추가할 각 요소가 먼저 await됩니다. mapFn
이 제공되면, 그 입력과 출력이 내부적으로 await 됩니다.
Array.fromAsync()
와 Promise.all()
은 모두 프로미스의 순회 가능을 배열의 프로미스로 변환할 수 있습니다. 하지만 두 가지 중요한 차이점이 있습니다.
Array.fromAsync()
는 객체에서 yield된 각 값을 순차적으로 await 합니다.Promise.all()
은 모든 값을 동시에 await 합니다.Array.fromAsync()
는 순회 가능을 지연(lazy) 순회하고, 현재 값이 확정될 때까지 다음 값을 가져오지 않습니다.Promise.all()
은 모든 값을 미리 가져오고 모두 await 합니다.
예제
비동기 순회 가능에서 배열 만들기
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]
동기 순회 가능에서 배열 만들기
Array.fromAsync(
new Map([
[1, 2],
[3, 4],
]),
).then((array) => console.log(array));
// [[1, 2], [3, 4]]
프로미스를 yield하는 동기 순회 가능에서 배열 만들기
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 사용하기
mapFn
의 입력과 출력은 모두 Array.fromAsync()
에서 내부적으로 await 됩니다.
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()
는 객체에서 yield 각 값을 순차적으로 await 합니다. Promise.all()
은 모든 값을 동시에 await 합니다.
function* makeAsyncIterable() {
for (let i = 0; i < 5; i++) {
yield new Promise((resolve) => setTimeout(resolve, 100));
}
}
(async () => {
console.time("Array.fromAsync() 시간");
await Array.fromAsync(makeAsyncIterable());
console.timeEnd("Array.fromAsync() 시간");
// Array.fromAsync() 시간: 503.610ms
console.time("Promise.all() 시간");
await Promise.all(makeAsyncIterable());
console.timeEnd("Promise.all() 시간");
// Promise.all() 시간: 101.728ms
})();
동기 순회 가능에 대한 오류 처리 없음
for await...of
의 경우와 마찬가지로, 순회되는 객체가 동기 순회 가능이고, 순회하는 동안 오류가 발생하면, 기본 반복자의 return()
메서드가 호출되지 않으므로 반복자가 종료되지 않습니다.
function* generatorWithRejectedPromises() {
try {
yield 0;
yield Promise.reject(3);
} finally {
console.log("finally 호출");
}
}
(async () => {
try {
await Array.fromAsync(generatorWithRejectedPromises());
} catch (e) {
console.log(e, "잡음");
}
})();
// 3 잡음
// "finally 호출" 메시지 없음
반복자를 종료해야 하는 경우, for...of
루프를 대신 사용하고, 각 값을 직접 await 해야 합니다.
(async () => {
const arr = [];
try {
for (const val of generatorWithRejectedPromises()) {
arr.push(await val);
}
} catch (e) {
console.log(e, "잡음");
}
})();
// finally 호출
// 3 잡음
명세서
Specification |
---|
ES Array.fromAsync (2022) # sec-array.fromAsync |
브라우저 호환성
BCD tables only load in the browser