jsのasyncなメソッドをfor,loop内で同期的に呼び出す

async/awaitを使ったjavascriptのコードをnodejsで使用する際、非同期呼び出しとなっている関数をloopの中で動機呼び出しする方法。

この前かなり真剣にPromiseのドキュメントを読んで、これをいずれ使うことになるのか、使いこなすの大変そうだな、と思っていたのですが、js,nodejsは既にその先に行っているそうで、それがasync/awaitとのこと。
で、詳しい説明はいろいろ書いてあったのですが、とりあえず脇に置いておいて、私にはasync/awaitの理解よりも先にやりたい作業があり、幸いWebから拾ってきた関数を使えば、使われているasync/awaitの詳細は気にしなくても良さそう....だったのですが。

例えばこういう関数があり、これはasyncにより非同期呼び出し関数になっています。
```
async function getPage(save_dir, year, month){
    // ブラウザを起動する
    const browser = await pptr.launch({
        //slowMo: 50,                // 実行にwaitを入れる
        args: ['--lang=ja,en-US,en']        // デフォルトでは言語設定が英語なので日本語に変更
    });

    // ページつくる
    const page = await browser.newPage();


    // 〜    ...以下略
}
```
こいつは中身に非同期関数をかなり使っており、単にasyncを外せば同期関数になるというものでもありません。

で、asyncされている関数をこういう呼び出しをすると、並列実行されてしまいます。
```
    for(let year = 2018; 2000 <= year; year--){
        for(let month = 1; month <= 12; month++){
            getPage(save_dir, year, month);
        }
    }

```
私の環境では12coreあるUbuntuマシンがフリーズしかけていました。
Ctrl+Cが効かないため、結局物理電源断。

で、対処法。
```
async function run(){
    for(let year = 2018; 2000 <= year; year--){
        for(let month = 1; month <= 12; month++){
            await getPage(save_dir, year, month);
        }
    }
}

run()

```

対象の呼び出しをawaitすればいい。
awaitするためには、呼び出しをasyncで囲んだ関数内でする必要があるようです。

これ、関数呼び出しの上の階層が必ず非同期になります。
上位階層で最終的に同期呼び出しがしたい場合にどうすればいいのかは不明。今回は必要ないので調べものはこれでおしまいでした。

0 件のコメント:

コメントを投稿

TIGORA(ティゴラ)のトレッキング シューズ

 TIGORA(ティゴラ)の トレッキング シューズを買いました。 メインの靴がアシックスウォーキングで街歩き用なのですが、これまではこれで高尾山などの軽い山も登っていました。 今回、靴底があまりに摩耗したこともあってアシックスウォーキングを買い替えたのですが、ついでに消耗が激...