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


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

やりたいこと

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

何からすればいいんだ

https://kde.hateblo.jp/entry/2018/10/22/010811
このサイトを参考にさせていただきました。

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.jsonfetchして、
成功したら(then) ,responseのデータをコンソールに表示してね!というところ。

fetchの成功はどんな成功?

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

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

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させます。

これで問題なく取得できますね。でも....

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

fetchで返ってくるレスポンスって?

【参考】https://qiita.com/uhyo/items/91649e260165b35fecd7
https://qiita.com/koheiyamaguchi0203/items/5777c4653a01ae4c7b06

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

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

本文の取得
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);
})

結果:

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

ページに書き出し(失敗例)
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>"; //書き出し部分
    })
})

結果:

ナンジャコリャ。どうも形式がオブジェクトじゃないみたい。

jsonをパースする

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

ページ書き出し(完成)
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等)を理解しないといけない
・ただ表示するだけじゃ味気ない、グラフ化する技術などをを身に付けたい