Array.fromAsync()
구문
js
Array.fromAsync(arrayLike)
Array.fromAsync(arrayLike, mapFn)
Array.fromAsync(arrayLike, mapFn, thisArg)
매개변수
반환 값
설명
Array.fromAsync()
은 다음으로부터 배열을 만들 수 있습니다.
- 비동기 순회 가능 객체(
ReadableStream
와AsyncGenerator
(en-US) 같은 객체). 또는, 객체가 비동기 순회 가능이 아니라면, - 순회 가능 객체(
Map
과Set
(en-US) 같은 객체). 또는, 객체가 순회 가능이 아니라면 - 유사 배열 객체(
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 합니다.
예제
비동기 순회 가능에서 배열 만들기
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]]
프로미스를 yield하는 동기 순회 가능에서 배열 만들기
js
Array.fromAsync(
new Set([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]),
).then((array) => console.log(array));
// [1, 2, 3]
프로미스 유사 배열 객체에서 배열 만들기
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()
에서 내부적으로 await 됩니다.
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()
는 객체에서 yield 각 값을 순차적으로 await 합니다. Promise.all()
은 모든 값을 동시에 await 합니다.
js
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()
메서드가 호출되지 않으므로 반복자가 종료되지 않습니다.
js
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 해야 합니다.
js
(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