request をループ処理する

`http request` をすると `response` があるまで少々の時間がかかります。
しかし、`node.js` では `response` を待たずに次の処理に進んでしまいます。
そのため、`response` を待って処理するためには、`promise` または `callback` を利用して非同期処理を行う必要があります。

`node.js` には `request-promise` モジュールがあり、こちらを使用することにより簡単に非同期処理を行うことができます。
※`request-promise` については過去に記事を書きましたのでこちらをご参照ください。
[Callback 使いから Promise マスターにクラスチェンジするぞ！](https://qiita.com/kunihiros/items/d05ea0ea551143e7b437)

と、諸先輩方には釈迦に説法なお話なのですが、自分の理解の定着のために書かせていただきました。
オレ、しっかり反復する。大事('ω')

さて、前置きはこのくらいにして、本題に入りましょう。

## ID から名前を取得して表示するプログラム
1. 『`ID` から `name` を検索する `API`』を `request` する
2. `response` を取得したら `ID` と `name` を表示する
3. 1～2 を ID リストの分だけ繰り返す

こんなループをするプログラムにしたいと思います。

## for や while を使ったループで request すると…？

単純にループさせるだけなら `for` や `while` を使えば実現します。

```js:request-loop.js
const idList = ["sample001@shop","sample002@shop","sample003@shop"];
class setOptions {
    constructor(id) {
        // API を request するためのオプションをセット（内容は割愛）
    }
}
for(let i = 0; i < idList.length; i++){ // 3 の処理
    request(new setOptions(idList[i])).then((response) => { // 1 の処理
        console.log(idList[i] + " : " + response); // 2 の処理
    }).catch((error) => { console.log(error) }); 
}
```
しかし、実行結果がこうなります。

```
sample002@shop : サンプル次郎
sample001@shop : サンプル太郎
sample003@shop : サンプル四郎
```
順番がバラバラですね。
結局、`for` や `while` を使う場合には非同期処理になるため、`response` を待たずに次の `request` を行ってしまうためです。
`for` がやっている実際の処理は、こんな感じなのでしょう。

```js:for部分の実際の処理
request(new setOptions(idList[0])).then((response) => {
    console.log(idList[0] + " : " + response);
}).catch((error) => { console.log(error) }); 
request(new setOptions(idList[1])).then((response) => {
    console.log(idList[1] + " : " + response);
}).catch((error) => { console.log(error) }); 
request(new setOptions(idList[2])).then((response) => {
    console.log(idList[2] + " : " + response);
}).catch((error) => { console.log(error) }); 
}
```
せっかくの `request-promise` でも、別々に呼び出してたら意味ありませんよね。
結局、非同期処理されて、順番は守られません。

本当は、こうしたいのです。

```js:こんな処理がしたい！
request(new setOptions(idList[0]))
.then((response) => {
    console.log(idList[0] + " : " + response);
    return request(new setOptions(idList[1]));
.then((response) => {
    console.log(idList[1] + " : " + response);
    return request(new setOptions(idList[2]));
.then((response) => {
    console.log(idList[2] + " : " + response);
}).catch((error) => { console.log(error) }); 
```
さて、これをループ処理にするには、どうしたら良いのでしょうか？

## 再起処理でループさせる
再起処理とは「自分自身を呼び出す処理が書かれている関数を呼び出すこと」です。
この方法であれば、`response` を待って処理することができます。

```js:request-loop.js
const idList = ["sample001@shop","sample002@shop","sample003@shop"];
class setOptions {
    constructor(id) {
        // API を request するためのオプションをセット（内容は割愛）
    }
}
function loop(i){
    request(new setOptions(idList[i]))
    .then((response) => {
        console.log(idList[i] + " : " + response);
        i++;
        if(i < idList.length) loop(i); // ここでループする
    }).catch((error) => { errorArart(error) });    
}
loop(0);
```

```
sample001@shop : サンプル太郎
sample002@shop : サンプル次郎
sample003@shop : サンプル四郎
```

API で取得した値を利用して、順番通り表示することができました！(*‘∀‘)やったね！

#おわりに
ここまでお付き合いいただきありがとうございました。

肝心の再起処理の部分がさらっと終わってしまったのですが、できたときは凄く嬉しかったです YO！('Д')
いや、ほんと。`for` 文でなんとかできないか四苦八苦していました。
まだまだ勉強が足りません。精進せな。

今回、メインではなかったので API 部分は割愛したのですが、今回の話を踏まえた上で、次回は LINEWORKS の API でやる方法を解説してみたいと思います。

ではまた！(^^)/

#参考にさせていただきましたm(_ _)m
[再帰処理とは (分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典)](https://wa3.i-3-i.info/word14899.html)