複数の非同期処理をうまく処理する【Web API編】


複数のWeb APIを叩いたりするときに複数の非同期処理をハンドリングする必要があったので、適当に書いた後どんどん変えていったら別物になりました。

今後のPromise活用に使うかもしれないので基本部分からまとめておきます。

準備

今回は非同期処理の中でも利用頻度の高いWeb APIを叩くことを考えます。

今回はサンプルとして使いやすいGithub APIを対象にいくつかリクエストを投げる。

https://developer.github.com/v3/search/

連続でAPIを叩くことになるのでリミットを確認。未認証で10 req/minのようです。

 

APIを叩くためにfetchを使いますがNode.jsで使えないためnode-fetchを使います。

基本的な非同期処理

後々のことを考えてAPI部分はモジュール化しておきます。

とりあえずNode.jsで使いやすいcommonJS形式で書きますがimport / exportの方が統一感があって気持ちいい気もする。

Promiseのままとasync / awaitで書いてますが、個人的には非常にシンプルなもの(api.js q())はthenチェーン、数行以上書くならawaitがやりやすいです。

正直new Promise((resolve, reject) => {...})とかはもう忘れていい気がする。

複数の非同期処理:直列

非同期処理1の結果を用いて非同期処理2を動かして…のようなパターン。

非同期処理が変に長引く原因になりますし使う機会はそんなにない。

書きやすさ・わかりやすさでは圧倒的にasync /awaitですね。

PromiseではなくCallback引数で指定するタイプの関数が混じっているとthenチェーンの方が書きやすいこともある。わりと気分次第。

複数の非同期処理:並列

複数の非同期処理を同時に行って全部終わったら結果を変えるパターン。

複数PromiseをPromise.all()で1つのPromiseにまとめて結果を得ます。

非同期処理を待つのは1回なので書き方を気にすることはあまりないけど、少しでもインデントが浅い方が好きなのでasync/awaitを使う方が多い。

今回はこのパターンのAPI処理からごちゃごちゃして使いやすい形に落とします。

変形、工夫、改造

まずPromise.then()Promiseを返すのを利用して前処理を行う。

ヒット数だけ返すようにした。

似たような処理が続くためクエリを抜き出してArray.map()でPromise配列にする。

結果の入った配列が何を表しているかわからないのが不満、というか後々の処理に回すときに不便になりそう。

 

対処法の1つとして前処理のところでオブジェクトにしてしまう方法があります。

使う側でArray.filter()など必要になるかもしれませんが、かなりわかりやすい。

ちなみに式だと{}を省略できることを利用していたのでそのままオブジェクトを返そうとすると文だと認識されてエラーになります。

 

もう1つは配列の分割代入からオブジェクトに設定する方法です。

あとは変数定義の手動部分をArray.reduce()とスプレッド構文(...acc)、変数値をキーにする書き方([queries[idx]])で対応。

クエリ(string)とプロミスと結果の配列が同数同順なのでこういう書き方ができます。

この場合、使う側はドット表記(.key)でなくブラケット表記(['key'])がよさそう。

ここまでくるとES6機能満載な感じになってきて割と好きです。

 

蛇足ですがクエリ列と結果格納を対応させる部分も一般化できそう。

配列を渡すと関数を返す関数を作り、他でも使えるようにしておきます。

読みやすさは変わらないけどコメントは付けやすくなりました。

 

こうして見返してみると変更前の方が読みやすい気もしてきましたが使いやすくはなりました。見やすさを向上させるならthen()内部の関数を外に出したり。


コメントを残す

メールアドレスが公開されることはありません。