JavaScript・外のデータを使う

fetch:外のデータを取り寄せる

天気やニュースなど、外のデータをページに表示する入口がfetchです。「時間がかかる処理を待つ」という考え方から、書き方の型、失敗したときの備えまでをまとめました。

天気予報を表示するページ、住所を自動で入れてくれるフォーム——どれも外にあるデータを取り寄せています。その入口がfetchです。

取り寄せは「時間がかかる」

いままでの命令は、書いた順にすぐ実行されました。でもインターネット越しのやりとりは違います。注文してから届くまで、待ち時間があるのです。

fetchを呼ぶ  →  (数百ミリ秒〜数秒)  →  データが届く

この「待ってから続きをやる」を書くための言葉がawait(アウェイト=待つ)です。

基本の形

async function getData() {
  const response = await fetch("https://example.com/api/weather");
  const data = await response.json();

  console.log(data);
}

getData();

覚えることは3つだけです。

書き方意味
async function「この関数の中では待つことがある」という宣言
await fetch(URL)そのURLからの返事が届くまで待つ
await response.json()返事の中身をJSONとして読み取る(これも待つ)

awaitが2回出てくるのが最初のつまずきどころです。1回目は「返事が届くまで」、2回目は「その中身を読み終わるまで」。届くことと、中身を読むことは別だと考えると腑に落ちます。

取り寄せたデータを画面に出す

届いたデータはJSONを読み取った結果=ふつうのオブジェクトです。あとは今までどおり扱えます。

async function showWeather() {
  const response = await fetch("https://example.com/api/weather");
  const data = await response.json();

  document.querySelector("#city").textContent = data.city;
  document.querySelector("#temp").textContent = data.weather.temp + "℃";
}

showWeather();
JavaScriptJSON:データをやりとりする形返ってくるデータの形(JSON)の読み方はこの回で

失敗したときの備え

ネットワークは、こちらの都合と関係なく失敗します。うまくいく前提だけで書かないのが実務の作法です。

async function showWeather() {
  try {
    const response = await fetch("https://example.com/api/weather");

    if (!response.ok) {
      throw new Error("サーバーがエラーを返しました: " + response.status);
    }

    const data = await response.json();
    document.querySelector("#city").textContent = data.city;
  } catch (error) {
    console.log(error);
    document.querySelector("#city").textContent = "読みこめませんでした";
  }
}
  • trycatch——失敗したときにcatchのほうへ処理が移る
  • response.ok——通信は成功したが、404などが返っている場合を拾う
  • 画面には「読みこめませんでした」と出す——利用者に空白を見せない

.then()という書き方も見かける

古い記事や他の人のコードでは、この形をよく見ます。

fetch("https://example.com/api/weather")
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.log(error));

やっていることはasync/awaitと同じです。読みやすさではawaitのほうが有利なので、これから書くならawaitで構いません。「見かけたら同じものだと分かる」程度で十分です。

CORS——他のサイトのデータは勝手に取れない

自分のページから別のドメインのデータを取ろうとすると、こんなエラーが出ることがあります。

Access to fetch at '...' from origin '...' has been blocked by CORS policy

これは取り寄せ先が「他のサイトからの読み取り」を許可していないという意味です。取り寄せる側では直せません。

  • 公開APIとして提供されているものを使う(許可の設定がされている)
  • 手元のHTMLファイルを直接ブラウザで開く(file://)のではなく、開発サーバー経由で開く(Live Serverなど)
べんりワザ開発者ツールの使い方入門開発者ツールの開き方から知りたい方はこちら

APIキーをHTMLに書かない

このレッスンのまとめ

  1. fetchは外のデータを取り寄せる命令。待ち時間があるのでawaitで待つ
  2. await fetch(URL)で返事を待ち、await response.json()で中身を読む——awaitは2回
  3. try/catchresponse.okで失敗に備える。APIキーはページに書かない

やってみよう

今回学んだ「fetch」は、しまちゃんのページには使いません(表示する内容はすべてHTMLに書いてあるためです)。天気・ニュース・住所の自動入力など、外のデータを使うページのための道具です。覚えておいて、必要になったら使いましょう。

よくある質問

fetchとは何ですか?
インターネット上のデータを取り寄せるためのJavaScriptの命令です。取り寄せ先のURL(API)を指定すると、そのデータが返ってきます。
awaitを付け忘れるとどうなりますか?
データそのものではなく「まだ届いていない」という入れ物(Promise)が返ってきます。中身を取り出そうとするとundefinedになるので、値がおかしいときはawaitの付け忘れを疑います。
CORSエラーとは何ですか?
取り寄せ先が「他のサイトからの読み取りを許可する」設定になっていないときに起こります。取り寄せる側では直せないので、公開APIとして提供されているものを使うのが基本です。