for await...of
Baseline
Widely available
This feature is well established and works across many devices and browser versions. Itâs been available across browsers since 2020å¹´1æ.
for await...of æã¯ãéåæå復å¯è½ãªãã¸ã§ã¯ãããåæå復å¯è½ãªãã¸ã§ã¯ãã¨åæ§ã«å復å¦çããã«ã¼ãã使ãã¾ãããã®æã¯ await ã使ç¨ã§ããã³ã³ããã¹ããä¾ãã°éåæé¢æ°ã®æ¬ä½ãã¢ã¸ã¥ã¼ã«å
ãªã©ã§ã®ã¿ä½¿ç¨ã§ãã¾ãã
試ãã¦ã¿ã¾ããã
async function* foo() {
yield 1;
yield 2;
}
(async () => {
for await (const num of foo()) {
console.log(num);
// äºæ³ãããçµæ: 1
break; // ã¤ãã¬ã¼ã¿ã¼ãéããæ»ãããã«ãã
}
})();
æ§æ
for await (variable of iterable)
statement
variable-
ä¸é£ã®å復å¦çã®ååã«ããã¦ãå¤ãåãåãã¾ãã
constãletãvarã®ä½ããã®å®£è¨ããä»£å ¥æã®ã¿ã¼ã²ããã¨ãªããã® ï¼ä¾ï¼åå宣è¨ããã夿°ããªãã¸ã§ã¯ãã®ããããã£ãã¾ãã¯æ§é åè§£ãã¿ã¼ã³ï¼ãæå®ãããã¨ãã§ãã¾ããvarãã¤ãã¦å®£è¨ããã夿°ã¯ãã«ã¼ãå ã®ã¹ã³ã¼ãã§ã¯ãªããã¤ã¾ãfor await...ofã«ã¼ãã¨åãã¹ã³ã¼ãå ã«åå¨ãã¾ãã iterable-
éåæå復å¯è½ãªãã¸ã§ã¯ãã¾ãã¯åæå復å¯è½ãªãã¸ã§ã¯ãããã®ã«ã¼ããå¦çããä¸é£ã®å¤ã®å ã¨ãªããã®ã§ãã
statement-
å復å¦çã®ãã³ã«å®è¡ãããæã§ãã
variableãåç §ãããã¨ãã§ãã¾ãããããã¯æã使ç¨ãã¦ãè¤æ°ã®æãå®è¡ãããã¨ãã§ãã¾ãã
解説
for await...of ã«ã¼ããå復å¯è½ãªãã¸ã§ã¯ããå復å¦çããå ´åãæåã«å復å¯è½ãªãã¸ã§ã¯ãã® [Symbol.asyncIterator]() ã¡ã½ãããåå¾ãã¦ãããå¼ã³åºãã¨ãéåæã¤ãã¬ã¼ã¿ã¼ãè¿ããã¾ãã@asyncIterator ã¡ã½ãããåå¨ããªãå ´åã¯ã次㫠[Symbol.iterator]() ã¡ã½ãããæ¢ããåæã¤ãã¬ã¼ã¿ã¼ãè¿ãã¾ããæ¬¡ã«ã next()ãreturn()ãthrow() ã¡ã½ããããè¿ããããã¹ã¦ã®ãªãã¸ã§ã¯ãã解決æ¸ã¿ã¾ãã¯æå¦æ¸ã¿ã®ãããã¹ã«ã©ããããvalue ããããã£ããããã¹ã§ããã°è§£æ±ºæ¸ã¿ã«ãããã¨ã§ãè¿ãããåæã¤ãã¬ã¼ã¿ã¼ãéåæã¤ãã¬ã¼ã¿ã¼ã«ã©ãããã¾ããã«ã¼ãã¯ãæçµçãªéåæã¤ãã¬ã¼ã¿ã¼ã® next() ã¡ã½ãããç¹°ãè¿ãå¼ã³åºãã¦ãè¿ããããããã¹ãå¾
ã¡ãvariable ã«ä»£å
¥ãããä¸é£ã®å¤ãçæãã¾ãã
for await...of ã«ã¼ãã¯ãã¤ãã¬ã¼ã¿ã¼ãå®äºããã¨ãï¼å¾
æ©å¼ã³åºããã next() ã done: true ã®å
¥ã£ããªãã¸ã§ã¯ãã¨ãè¿ããã¨ãï¼ã«çµäºãã¾ããä»ã®ã«ã¼ãæã®ããã«ãå¶å¾¡ããã¼æã statement ã®å
é¨ã§ä½¿ç¨ãããã¨ãã§ãã¾ãã
breakã¯statementã®å®è¡ã䏿¢ããã«ã¼ãå¾ã®æåã®æã«ç§»åãã¾ããcontinueã¯statementã®å®è¡ã䏿¢ãããã®ã«ã¼ãã®æ¬¡ã®å復ã«ç§»åãã¾ãã
for await...of ã«ã¼ããæ©æã«çµäºããå ´åï¼ä¾ãã°ãbreak æã«ééããããã¨ã©ã¼ã throw ãããå ´åï¼ãã¯ãªã¼ã³ã¢ãããå®è¡ããããã«ã¤ãã¬ã¼ã¿ã¼ã® return() ã¡ã½ãããå¼ã³åºããã¾ããè¿ããããããã¹ã¯ãã«ã¼ããçµäºããåã«å¾
æ©ããã¾ãã
for await...of ã¯å
¨è¬çã« for...of ã«ã¼ãã¨åæ§ã«æ©è½ããæ§æãæå³ãå
±éãã¦ãã¾ããããããéããããã¾ãã
for await...ofã¯åæã¾ãã¯éåæã®å復å¯è½ãªãã¸ã§ã¯ãã§åä½ãã¾ãããfor...ofã¯åæå復å¯è½ãªãã¸ã§ã¯ãã§ã®ã¿åä½ãã¾ããfor await...ofã¯awaitã使ããã³ã³ããã¹ãã§ã®ã¿ä½¿ç¨ã§ãã¾ããããã¯éåæé¢æ°ã®æ¬ä½ãã¢ã¸ã¥ã¼ã«å ãªã©ã§ããå復å¯è½ãªãã¸ã§ã¯ããåæã®å ´åã§ããã«ã¼ãã¯å復å¦çã®ãã³ã«è¿å¤ãå¾ ã¤ãã¨ã«ãªãããããã¹ã®ã©ããè§£é¤ãç¹°ãè¿ãããå®è¡é度ãé ããªãã¾ããiterableããããã¹ãçæããåæå復å¯è½ãªãã¸ã§ã¯ãã§ããå ´åãfor await...ofã¯è§£æ±ºãããå¤ã®ã·ã¼ã±ã³ã¹ãçæããã®ã«å¯¾ãfor...ofã¯ãããã¹ã®ã·ã¼ã±ã³ã¹ãçæãã¾ããï¼ãã ããã¨ã©ã¼å¦çã¨å¾å§æ«ã«ã¯æ³¨æãå¿ è¦ã§ããåæã®å復å¯è½ãªãã¸ã§ã¯ãããã³ã¸ã§ãã¬ã¼ã¿ã¼ã®å復å¦çãåç §ãã¦ãã ãããï¼for await...ofã§ã¯ãvariableã«èå¥åasyncãåããã¨ãã§ãã¾ãï¼ä¾ãã°for await (async of foo)ï¼ãfor...ofã§ã¯ç¦æ¢ããã¦ãã¾ãã
for...of ã¨åæ§ãusing 宣è¨ã使ç¨ããå ´åãof ã¨ããååã®å¤æ°ãå¼ã³åºããã¨ã¯ã§ãã¾ããã
for await (using of of []); // SyntaxError
ãã㯠using ãå°å
¥ããã以åãæå¹ãªã³ã¼ãã§ãã£ã for await (using of []) ã¨ã®æ§æçãªããã¾ãããé¿ããããã§ãã
ä¾
>éåæã®å復å¯è½ãªãã¸ã§ã¯ãã§ã®ç¹°ãè¿ãå¦ç
éåæå復å¯è½ãããã³ã«ãæç¤ºçã«å®è£ ãã¦ãããªãã¸ã§ã¯ããå復å¦çãããã¨ãã§ãã¾ãã
const LIMIT = 3;
const asyncIterable = {
[Symbol.asyncIterator]() {
let i = 0;
return {
next() {
const done = i === LIMIT;
const value = done ? undefined : i++;
return Promise.resolve({ value, done });
},
return() {
// ã«ã¼ãã®æ©ã段éã§æ¶è²»è
ã 'break' ã¾ã㯠'return' ãå¼ã³åºããå ´åã«ãããã«å°éãã¾ãã
return { done: true };
},
};
},
};
(async () => {
for await (const num of asyncIterable) {
console.log(num);
}
})();
// 0
// 1
// 2
éåæã®ã¸ã§ãã¬ã¼ã¿ã®å復å¦ç
éåæã®å復å¯è½ãããã³ã«ãå®è£
ãã¦ããéåæã¸ã§ãã¬ã¼ã¿ã¼ã§ããã°ã for await...of ã使ç¨ãã¦å復å¦çãè¡ããã¨ãã§ãã¾ãã
async function* asyncGenerator() {
let i = 0;
while (i < 3) {
yield i++;
}
}
(async () => {
for await (const num of asyncGenerator()) {
console.log(num);
}
})();
// 0
// 1
// 2
for await...of ã使ç¨ãã¦éåæã¸ã§ãã¬ã¼ã¿ãå復å¦çããããå
·ä½çãªä¾ã¨ãã¦ãAPI ããã®ãã¼ã¿ãå復å¦çãããã¨ãèãã¦ã¿ã¾ãããã
ãã®ä¾ã§ã¯ãã¾ããã¼ã¿ã®ã¹ããªã¼ã ã«å¯¾ãã¦éåæã®å復å¯è½ãªãã¸ã§ã¯ãã使ããããã使ç¨ã㦠API ããã®ã¬ã¹ãã³ã¹ã®é·ããè¨ç®ãã¾ãã
async function* streamAsyncIterable(stream) {
const reader = stream.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) return;
yield value;
}
} finally {
reader.releaseLock();
}
}
// URL ãããã¼ã¿ãåå¾ããéåæã¸ã§ãã¬ã¼ã¿ã使ç¨ãã¦ã¬ã¹ãã³ã¹ã®é·ããè¨ç®ãã¾ãã
async function getResponseSize(url) {
const response = await fetch(url);
// ã¬ã¹ãã³ã¹ã®é·ãããã¤ãåä½ã§ä¿æãã
let responseSize = 0;
// for-await-of ã«ã¼ããã¬ã¹ãã³ã¹ã®åé¨åãéåæã«å復å¦çãã¾ãã
for await (const chunk of streamAsyncIterable(response.body)) {
// ã¬ã¹ãã³ã¹ã®å
¨é·ã«å ç®
responseSize += chunk.length;
}
console.log(`Response Size: ${responseSize} bytes`); // "Response Size: 1071472"
return responseSize;
}
getResponseSize("https://jsonplaceholder.typicode.com/photos");
åæã®å復å¯è½ãªãã¸ã§ã¯ãããã³ã¸ã§ãã¬ã¼ã¿ã¼ã®å復å¦ç
for await...of ã«ã¼ãã¯åæã®å復å¯è½ãªãã¸ã§ã¯ããã¸ã§ãã¬ã¼ã¿ã¼ã§ä½¿ç¨ãããã¨ãã§ãã¾ãããã®å ´åãå
é¨çã«ã¯ã«ã¼ãã®å¶å¾¡å¤æ°ã«ä»£å
¥ããåã«ãå¤ãåºåãããã®ãå¾
ã¡ã¾ãã
function* generator() {
yield 0;
yield 1;
yield Promise.resolve(2);
yield Promise.resolve(3);
yield 4;
}
(async () => {
for await (const num of generator()) {
console.log(num);
}
})();
// 0
// 1
// 2
// 3
// 4
// for-of ã«ã¼ãã¨ã®æ¯è¼:
for (const numOrPromise of generator()) {
console.log(numOrPromise);
}
// 0
// 1
// Promise { 2 }
// Promise { 3 }
// 4
ã¡ã¢:
åæã¸ã§ãã¬ã¼ã¿ã¼ããæå¦ããããããã¹ãçã¿åºãããå ´åããããã¨ã«æ³¨æãã¦ãã ããããã®ãããªå ´åãfor await...of ã¯æå¦ããããããã¹ãæ¶è²»ããã®ã§ãã¸ã§ãã¬ã¼ã¿ã¼å
ã® finally ãããã¯ãå¼ã³åºããã¾ãããããã¯ã確ä¿ãããªã½ã¼ã¹ã try/finally ã§è§£æ¾ããå¿
è¦ãããå ´åã¯æã¾ãããªãåä½ã«ãªãå¯è½æ§ãããã¾ãã
function* generatorWithRejectedPromises() {
try {
yield 0;
yield 1;
yield Promise.resolve(2);
yield Promise.reject(new Error("failed"));
yield 4;
throw new Error("throws");
} finally {
console.log("called finally");
}
}
(async () => {
try {
for await (const num of generatorWithRejectedPromises()) {
console.log(num);
}
} catch (e) {
console.log("caught", e);
}
})();
// 0
// 1
// 2
// caught Error: failed
// compare with for-of loop:
try {
for (const numOrPromise of generatorWithRejectedPromises()) {
console.log(numOrPromise);
}
} catch (e) {
console.log("caught", e);
}
// 0
// 1
// Promise { 2 }
// Promise { <rejected> Error: failed }
// 4
// caught Error: throws
// called finally
åæã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ã® finally ãããã¯ã常ã«å¼ã³åºãããããã«ããã«ã¯ãéåæã®ã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ã®å ´å㯠for await...of ããåæã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ã®å ´å㯠for...of ã使ç¨ããã«ã¼ãã®ä¸ã§çæããããããã¹ãæç¤ºçã«å¾
ã¤ããã«ãã¦ãã ããã
(async () => {
try {
for (const numOrPromise of generatorWithRejectedPromises()) {
console.log(await numOrPromise);
}
} catch (e) {
console.log("caught", e);
}
})();
// 0
// 1
// 2
// caught Error: failed
// called finally
仿§æ¸
| Specification |
|---|
| ECMAScript® 2027 Language Specification> # sec-for-in-and-for-of-statements> |