【初学】初めてのAPI（fetchとかpromiseとか良くわからない)


fetchなんて一度も使ったことない！
って状態から、なんとか簡単なAPIの加工までできたのでメモしておきます。

##やりたいこと
https://holidays-jp.github.io/
このAPIを使って、画面上に簡単に加工したデータを表示したい！

##何からすればいいんだ
https://kde.hateblo.jp/entry/2018/10/22/010811
このサイトを参考にさせていただきました。

```javascript
fetch("https://holidays-jp.github.io/api/v1/date.json")
.then(response =>{
   console.log(response);
});
```

ちゃんとAPIから取得したデータが表示されました！感動！

###fetchってなんなのさ
fetchでデータを取ると、返り値として`Promise`を返す。
###Promiseってなんなのさ
まだちゃんと詳しく理解していない、、（今度勉強します）
非同期の状態として`reject(失敗）`と`resolved（成功）`があって、
成功時は`.then`以降の処理を実行させ、失敗時は`.catch`以降の処理を実行できる模様。

つまり上の例のコードは、
https://holidays-jp.github.io/api/v1/date.json を`fetch`して、
成功したら(`then`) ,responseのデータをコンソールに表示してね！というところ。

##fetchの成功はどんな成功？
→リクエストを投げてレスポンスを取ることに成功したら。
ここに落とし穴があって、**レスポンスが404(サーバーには接続できたけどサイトが見つからなかった）や500（内部サーバーエラー）でもrejectされない！**
確かにエラーのレスポンスを取ることには成功しているから、、でもこれじゃ色々困ります。

そこで、`response.ok`を使いました。
200-299 の範囲のステータスであれば、true、そうでなければfalseを返してくれます。

```javascript
fetch("https://holidays-jp.github.io/api/v1/date.json")
.then(response =>{
    if(response.ok){
        return console.log(response);
    }else{
        return Promise.reject(new Error('エラーです'));
    }
})
```

response.ok = trueだったら、レスポンスデータを表示、
そうじゃなかったら、プロミスをrejectさせます。

これで問題なく取得できますね。でも....
![UNADJUSTEDNONRAW_mini_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/5f43779a-896f-22e5-4dd7-e226bc05f9c2.jpeg)

この取得されたデータから、祝日がいつなのかさっぱりですね。

##fetchで返ってくるレスポンスって？
【参考】https://qiita.com/uhyo/items/91649e260165b35fecd7
https://qiita.com/koheiyamaguchi0203/items/5777c4653a01ae4c7b06

レスポンスというのは３つの構成に別れていて、
・ステータスコード
・レスポンスヘッダー
・本文（レスポンスボディ）
の順になっています。私が欲しいのはもちろん**本文**です。

でも、fetchが返されるタイミングは**レスポンスヘッダーが全部返ってきたとき**なのです。
「本文を下さい！」ということで、本文をテキストとして取得します。

```javascript:本文の取得
fetch("https://holidays-jp.github.io/api/v1/date.json")
.then(response=>{
    if(response.ok){
        return response.text();    //文字列として取得
    }else{
        return Promise.reject(new Error('エラーです'));
    }
})
.then(response =>{
    console.log(response);
})
```

結果：
![2019-07-12 12.20のイメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/f6af5d63-64b3-cd43-a1da-03c77eb368be.jpeg)

おお！休日がズラッと取得できました！（text()以外にも取得の形式指定は色々あるようです。）
オブジェクトっぽいですね。早速ページに書き出してみます。

```JavaScript:ページに書き出し（失敗例）
var holiday = document.getElementById('holiday');  //ここに書き出す

.then(response =>{
    if(response.ok){
        return response.text();
    }else{
        return Promise.reject(new Error('エラーです'));
    }
})
.then(response =>{
    Object.keys(response).forEach(function(key){
        holiday.innerHTML += response[key] + "は" + key + "<br>"; //書き出し部分
    })
})
```

結果：
![2019-07-12 12.27のイメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441432/eb8bf394-3981-9577-2b08-778b6ed1e706.jpeg)
ナンジャコリャ。どうも形式がオブジェクトじゃないみたい。

##jsonをパースする
【参考】https://qiita.com/mitsuhiro_K/items/2d179632f62a591a1582
この返ってくるデータはjson形式というもので（APIの仕様書に書いてあります）、json形式はパース（=オブジェクト形式に変換し直す)を行わないといけないようです。

```javascript:ページ書き出し（完成）
var holiday = document.getElementById('holiday');

//祝日一覧API
fetch("https://holidays-jp.github.io/api/v1/date.json")
.then(response=>{
    if(response.ok){
        return response.text();
    }else{
        return Promise.reject(new Error('エラーです'));
    }
})
.then(response =>{
    var objRes = JSON.parse(response);
    console.log(objRes);
    Object.keys(objRes).forEach(function(key){
        holiday.innerHTML += objRes[key] + "は" + key + "<br>";
    });
})
```

ちゃんと休みの日が一覧で表示できました！

##今後の課題👀
・もっと非同期関連の理屈（promise,fetch等）を理解しないといけない
・ただ表示するだけじゃ味気ない、グラフ化する技術などをを身に付けたい