ばかおもちゃ本店:Youtube twitter:@sashimizakana Amazon.co.jpアソシエイト

2017年6月6日火曜日

Node.jsネイティブのasyncとawait

Node.jsのv7.6からasync awaitが使えるようになった。これは非同期処理の可読性を向上させるための機能で、asyncで宣言した関数はすべての戻り値がPromiseとして返されるようになる。つまり、
async function hoge(){
    return 1; //return Promise.resolve(1)と同じ
}

みたいな感じになる。これはこの関数が非同期だという宣言だからだけど、より具体的な利便性の向上としては、async関数内ではawaitが利用できるということがある。awaitは他の非同期の関数(Promiseを返すもの。async関数じゃなくても良い)を同期的な処理のように待ち受けできるということにある。
async function hoge(){
    const result = await fuga();//promiseを返す非同期の処理
    return hogefuga(result);//fugaがpromiseを解決してから処理される
}

awaitを待つとはいえ、そこはasync宣言がされた非同期処理内なので処理がブロックされるということではない。順序をどおりに処理が呼び出されるというだけである(Promiseがチェインするように書いたときと同じように)。
ちなみにawaitで宣言した場合、resolveに渡されたものはそのまま戻り値になり、rejectされたものは例外として投げられる。そのためrejectされる可能性がある場合はtry,catchで処理しなければならない。

あと意外と忘れがちなのが、awaitを使うときは、それが直接含まれる関数がasyncではなければならないということ。これはアロー関数も含まれるので、forEachとかmapとかにcallbackを渡して使ったときに忘れがち。
function hoge(list){
    list.forEach(async (e)=>{  // ← ここがちゃんとasyncになっている必要がある
        await a(e);
        await b(e);
    });
}

ちなみに上記の処理の場合、list内の要素への処理が順番に実行されるという保証はない。(各要素eにa,bの順番で呼び出されることは保証されてる)。この場合だとlistの各要素への処理順序も守りたい場合は、普通にfor文を使って処理するのが手っ取り早い。