async/await
async/await構文
function parseJSONAsync(json) {
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
resolve(JSON.parse(json))
} catch (err) {
reject(err)
}
}, 1000)
})
}
async function asyncFunc(json) {
try{
const result = await parseJSONAsync(json);
console.log('パース結果', result);
}catch (err) {
console.log('エラーをキャッチ', err);
}
}
asyncFunc('{"foo": 1}')
asyncFunc('不正なJSON')
>>>
ース結果 { foo: 1 }
エラーをキャッチ SyntaxError: Unexpected token 不 in JSON at position 0
at JSON.parse (<anonymous>)
...(省略)
asyncキーワードの付いた関数は必ずPromiseインスタンスを返します。それは関数内で非同期処理が実行されない場合でも、同様です。
async function asyncReturnFoo() { return 'foo' }
const result = asyncReturnFoo()
console.log(result)
>>>
Promise { 'foo' }
また、async関数内でエラーが投げられると、async関数はrejectedなPromiseインスタンスを返します。
async function asyncTrhow() { throw new Error('エラー') }
const result = asyncTrhow()
console.log(result)
>>>
Promise {
<rejected> Error: エラー
...(省略)
}
(node:23161) UnhandledPromiseRejectionWarning: Error: エラー
...(省略)
awaitはasync関数ないの処理を一時停止するものの、非同期I/Oのようにスレッドの処理をブロックするわけではありません。asunc関数が一時停止している間も、async関数の外の処理は動作を続けます。
async function pauseAndResume(pausePeriod) {
console.log('pauseAndResume開始')
await new Promise(resolve => setTimeout(resolve, pausePeriod))
console.log('pauseAndResume終了')
}
pauseAndResume(1000)
console.log('async関数外の処理はawaitの影響を受けない')
>>>
pauseAndResume開始
async関数外の処理はawaitの影響を受けない
pauseAndResume終了
並行処理
async/await構文には並行実行のための機能はないため、Promise.all()などのスタティックメソッドと組み合わせる必要がある。
async function doSomethingAsyncConcurrently() {
const result = await Promise.all([
asyncFunc1(),
asyncFunc2(),
asyncFunc3()
]);
}
for await ...of 構文
for await ... of はasyncイテラブルに対して反復処理を行います。
asyncジェネレータ関数を使って簡単な例を書いてみます。
sync function* asyncGenerator() {
let i = 0;
while(i <= 3) {
await new Promise(resolve => setTimeout(resolve, 1000));
yield i++
}
}
for await (const value of asyncGenerator()) {
console.log(value);
}
>>>
0
1
2
3