0
0

More than 3 years have passed since last update.

[Node.js] 非同期処理 - async/await編

Posted at

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
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0