JSのfetch()メソッドと非同期通信

【JavaScript】初めて学ぶ!fetch()メソッドと非同期通信

こんにちは。
朝活でジムに行ったらその後二日間筋肉痛で動けなくなりました・・・いのうえです。

今回は、JavaScriptのfetch()メソッドと非同期通信について解説をしていきます。
プログラミングの勉強をしていると知らない単語や専門用語が当たり前のように出てきて、結局よく分からない・・・なんてことがありますよね。

この記事は、難しい用語が出てきてがっつり理解を深めるようなものではなく、「初学の方でも概要とポイントが掴める」ことを目的にしています。

fetchについて勉強したいと思っている方の最初のステップになれば幸いです。

最後には基本的な使い方としてサンプルのコードも書いていますので、参考にしてみて下さい!

fetchの意味

そもそも、fetch(フェッチ)という言葉の意味はご存知でしょうか。
和訳すると、取ってくる、呼び出す、引き出すという意味合いになります。

私の感覚ですが、分からない用語がでてきた場合はまず和訳することをおすすめします!

ではこの意味を頭に置いて、次に進みましょう。

fetch()メソッドとは?

JavaScriptのfetch()メソッドは、
「非同期通信でリクエストを発行、そのレスポンスを取得」することができる関数です。

・・・と、ネットで調べると大体このようなことが書かれているのではないでしょうか。正直、この時点で私はちんぷんかんぷんでした。

つまりは、
「非同期通信という方法で、サーバ上にある欲しいデータを取得できる」ということのようです。
(先ほどの和訳でも、取ってくるとかそんな意味がありましたね!)

fetch()メソッドの理解には、リクエスト・レスポンス、非同期通信とは何か?を理解する必要がありそうです。
WEBページの仕組みもおさらいしつつ、順番に確認していきましょう!

WEBページの仕組みから見る リクエストとレスポンス

WEBページの仕組みにおけるリクエストとレスポンスは以下の通りです。

■画面にWEBページを表示する仕組み
WEBページの表示は、
ブラウザ上で「このWEBページが見たいよ!」というリクエスト(要求)を送信し、
サーバが「これがWEBページの情報だよ!」とレスポンス(応答)を返すことで成り立っています。

普段あまり意識していませんが、
私たちがWEBサイトを見る際には「ここのWEBページ情報を見せて!」というリクエスト(要求)を必ず送っています。

そして、レスポンス(応答)として取得するWEBページの情報というのが
文章が書かれたHTMLファイルやデザインを調整するCSSファイル、画像データだったりして、画面には見慣れたWEBページが整形される、と言う訳です。


ここまでの内容を踏まえると、
fetch()メソッドの説明にある「リクエスト発行とレスポンスの取得」とは、
「サーバ上にある欲しいデータをfetch(取得)できる」
という意味であることを改めて理解できるのではないでしょうか。

非同期通信について

前項で説明の通り、ブラウザとサーバの通信でデータ取得をするには「リクエストとレスポンス」のやり取りが発生するのですが、
通常の場合、これは「同期通信」というもので行われています。

例えば、WEBページの表示や遷移・更新をすると、画面が一瞬真っ白になってから表示されますが、この真っ白な状態の時にサイトの操作など他の処理は出来ませんよね。

このようにリクエストに対してのレスポンスを受け取るまで、次の処理を行えず待ち続けなくてはいけないのが「同期通信」です。

「非同期通信」はその反対で、
リクエストを送信してからレスポンスを受け取るまでの間に、他の処理を行うことができます。

普段目にすることが多い非同期通信の例としては、Googleサジェストが挙げられます。Googleの検索エンジンを使っていると、以下のような場面をよく見ませんか?

検索したいキーワードを入力すると、候補一覧がフォームの下に自動で表示されるコレです。

これは1字入力する毎に検索候補をサーバにリクエストし、そのレスポンスをページに反映しているのですが、レスポンス取得の最中でも文字を入力したりと他の処理を行えます。

非同期通信は、
同期通信のような待ち時間がなく、引き続き別の処理を行えるという点でユーザビリティの向上に繋がっています。

fetchについて(再掲)

ここまでfetchの概要を掴むために色々説明をしましたが、

サーバに欲しいデータのリクエストを送信したら、そのレスポンスを待ちつつ、別の処理も進められるよ!
というポイントを押さえられていればOKです。

Fetch APIについて

fetchについて調べていると「Fetch API」という言葉もよく出てきます。
APIとは、ソフトウェアやプログラムを繋ぐものという意味です。

「Fetch API」は、外部とプログラムを繋げることができる窓口のようなものであり、
fetch()メソッドは、リクエストの発行とレスポンスを取得する関数(プログラムの一部)です。

なんだかややこしいですが、・・・
Fetch APIという窓口があることで、JavaScriptのfetchを利用して外部のデータ取得が可能になってるよ!」ということですね。

XMLHttpRequestとの違い

fetchと同じく「リクエストを発行、レスポンスを取得」できるのが、XMLHttpRequestと呼ばれるものです。

正しく言うと、元々はXMLHttpRequestが長らくその機能を果たしていたのですが、後にfetchが代替として登場してきたという背景があります。

ここではXMLHttpRequestについて詳しく説明はしませんが、違いを少しだけご紹介します。

fetchは直感的・分かりやすいコードで扱える

簡単な例として、単純にリクエスト送信するだけのコードを比較してみます。

■fetch

fetch("URL");

■XMLHttpRequest

var xhr= new XMLHttpRequest();
xhr.open("GET","URL");
xhr.send();

コードを見ただけで、XMLHttpRequest はコード量が多くて分かりにくい印象を受けますね。

コードを少し紐解いてみると、

var xhr= new XMLHttpRequest(); //XMLHttpRequestを呼び出して、
xhr.open("GET","URL");  //通信の設定をして、
xhr.send();  //通信を開始する

という記述になっているのですが、
どこかまとまりがなく、取っ付きにくそうなコードだと感じてしまいます。

fetchは返す値がPromiseベース

Promiseとは、処理が成功したか失敗したかという状態を表すオブジェクトで、その状態によって後続処理をうまくコントロールしてくれるものです。

前提として、
非同期で行なった通信は必ず成功する訳ではありません。
最終的な処理の状態は、「成功」か「失敗」かどちらかになります。

成功した場合の後続処理には、取得したデータをどのように扱うかを指定したいでしょうし、
失敗した場合の後続処理には、失敗したよ!と通知を送るものを指定したいかもしれません。
どちらにせよデータ取得後の処理は、データ取得の可否を考慮してそれぞれ記述する必要がありますよね。

この「データ取得をするコード」と「データ取得後の処理をするコード」を分散させることなく、
「成功 or 失敗を表す→それぞれの場合の処理」までを一連のコードで示せるのがPromiseオブジェクトになります。

fetchは、非同期の処理結果をこのPromiseオブジェクトで渡してくれるので、
成功したらこの処理をしてね!、失敗したらこっちの処理をして!という通信後の処理もシンプルに記述することができます。

基本的な使い方

有り難いことに頼れる先輩がAPIを作成してくれたので、fetch()メソッドの基本的な使い方をデータ取得しながら見ていきましょう。

まずは、リクエストの発行。

fetch("https://script.google.com/macros/s/AKfycbx59mSU5gTZ_FExAwaZrgjEorUcuki0AqGnh_XYn5uyZi_RSYzJ/exec");


返ってくる値をデベロッパーツールのコンソールで見たのが下の画像です。
説明した通り、Promiseになっていることがわかります。

しかし、これではさっぱり分からないので、データの中身が見れるようにしましょう。
Promiseは後続処理を一連のコードで記述できるんでしたよね!
では、fetchの後にコードを続けて書いていきます。

fetch("https://script.google.com/macros/s/AKfycbx59mSU5gTZ_FExAwaZrgjEorUcuki0AqGnh_XYn5uyZi_RSYzJ/exec")
  .then(response => {
    return response.json();
  })
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.log("失敗しました");
});

これで、通信が成功したときと失敗したときの後続処理の記述ができました。

2〜7行目が成功した時の設定で、then以降の処理が実行されます。
8〜10行目で失敗した時の設定で、catch以降の処理が実行されます。
※説明が後になってしまいましたが、Promiseはthenとcatchを使用することで、コードを繋げて記述できます。

【メモ】
成功した場合 ・・・ then(成功の場合の処理内容);を実行
失敗した場合 ・・・ catch(失敗の場合の処理内容);を実行

というわけで、今回のデータ取得の結果は以下のようになっています。

しっかりと中のデータが見えるようになりました!
今回は通信が成功したので、取得したデータをコンソールに表示してくれていますね。

このコードではJSON形式でデータを受け取っていますが、必要に応じて他の形式で受け取ることも可能です。
下記はそれぞれのサンプルです。

形式:text

fetch("URL")
  .then(response => {
    return response.text();
  })
  .then(text => {
    console.log(text);
  })
  .catch(error => {
    console.log("失敗しました");
});

形式:arrayBuffer

fetch("URL")
  .then(response => {
    return response.arrayBuffer();
  })
  .then(arrayBuffer => {
    console.log(arrayBuffer);
  })
  .catch(error => {
    console.log("失敗しました");
});

形式:blob

fetch("URL")
  .then(response => {
    return response.blob();
  })
  .then(blob => {
    console.log(blob);
  })
  .catch(error => {
    console.log("失敗しました");
});

それぞれの形式については、私も勉強中になります(^^;

データ取得の基本を説明しましたが、理解を深めることでより実践的な処理ができるようになりそうですね。
気になるものがあれば、ぜひ調べてみて下さい!

まとめ

fetchについての解説は以上です。
私自身まだまだ勉強途中ですが、今回記事としてまとめることで、頭の整理ができる良い機会となりました!

個人的に、非同期での処理はイメージしづらいし難しい・・・という印象を受けてしまうのですが、使いこなせたらカッコイイじゃん!というよこしまな気持ちを原動力にして頑張ります(笑)
最後までご覧いただき、ありがとうございました。

JavaScriptについては他の記事でも取り上げていますのでそちらもぜひ見てみてください。

作者情報

アウトドア好きの運動音痴。体を動かした後のお酒とご飯が美味しくて今日も生きてます。趣味は旅行で、暖かい地域によく出没します。
宜しくお願いします。