こんにちは、かつコーチです。
前回は「コピーボタン(Clipboard API)を実装する」で、ブラウザの便利な機能をJavaScriptから操作する方法を紹介しました。
今回からは、Webサイト作りで避けて通れない「外部データの取得」について解説していきます。
その第一歩として、fetch という関数の基本の使い方を押さえていきましょう。
fetch APIとは?
そもそも「外部データを取得する」とはどういうことか
WebサイトやWebアプリは、表示するデータを毎回自分のページの中だけに書いているわけではありません。
天気予報アプリなら気象情報のサーバーから、ニュースサイトなら記事データを管理しているサーバーから、必要な情報を取ってきて画面に表示しています。
このように「別の場所(サーバー)にあるデータを、こちらから取りに行く」処理のことを、API通信と呼びます。
API(Application Programming Interface)とは、あるプログラムが別のプログラムとやり取りするための「窓口」のようなものだと考えてください。
fetch関数の役割
fetch は、このAPI通信をJavaScriptから簡単に行うためのブラウザ標準の関数です。
以前はAPI通信のために XMLHttpRequest という少し書き方が複雑な仕組みを使っていましたが、fetch の登場でぐっとシンプルに書けるようになりました。
特別なライブラリを読み込まなくても、ブラウザで動くJavaScriptなら基本的にそのまま使えます。
fetchが返す「Promise」という考え方
fetch を理解するうえで欠かせないのが、Promise(プロミス)という概念です。
Promiseとは、「今すぐには終わらないけど、いつか結果が返ってくる処理」を表すオブジェクトのことです。
サーバーとの通信は、返事が返ってくるまでに一瞬〜数秒かかります。
その「待っている間」を表現する仕組みがPromiseだとイメージしてください。
fetchの基本の書き方
最小限のコード例
まずは、実際に外部のAPIからデータを取得する一番シンプルな形を見てみましょう。
fetch("https://jsonplaceholder.typicode.com/users/1")
.then((response) => response.json())
.then((data) => {
console.log(data);
});
このコードは次の3ステップで動いています。
fetch(url)で指定したURLにリクエストを送る- 返ってきた
response(レスポンス)を.json()でJavaScriptが扱えるデータ形式に変換する - 変換されたデータ(
data)をコンソールに出力する
.then() は「この処理が終わったら、次にこれをやってね」という意味のメソッドです。
Promiseの結果を受け取って、次の処理につなげる役割を持っています。
async/awaitで書き換える
.then() を連鎖させる書き方に加えて、async/awaitを使うとより読みやすいコードになります。
async function getUser() {
const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
const data = await response.json();
console.log(data);
}
getUser();
await は「Promiseの結果が返ってくるまで、ここで一旦待つ」という意味の書き方です。
.then() を並べるより、上から下に処理を読める分、初心者にとっては理解しやすいことが多いです。
この記事では、async/await形式を中心に解説していきます。
fetchが実行する処理の順番を確認する
fetchは「非同期処理」なので、コードの見た目の順番と、実際に処理が終わる順番が一致しないことがあります。
console.log("1: リクエスト開始前");
async function getUser() {
console.log("2: fetch実行");
const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
const data = await response.json();
console.log("4: データ取得完了", data.name);
}
getUser();
console.log("3: getUser呼び出し直後(awaitの結果を待たずに実行される)");
このコードを実行すると、コンソールには「1」「2」「3」「4」の順番で出力されます。
await が付いている行の処理が終わるのを待っている間も、それ以外のコードはどんどん先に進んでしまう、というのがポイントです。
つまずきやすいポイント
awaitを付け忘れる
私が最初にfetchを触ったとき、一番混乱したのが「awaitの付け忘れ」でした。
❌ Before:awaitを付けずにデータを使おうとする
async function getUser() {
const response = fetch("https://jsonplaceholder.typicode.com/users/1"); // awaitがない
const data = response.json(); // ここでエラーになる
console.log(data);
}
getUser();
// TypeError: response.json is not a function
await を付けないと、response には「まだ結果が返ってきていないPromiseそのもの」が入ってしまいます。
Promiseオブジェクトには .json() というメソッドがないため、response.json is not a function というエラーになります。
私はこのエラーメッセージを見たとき、最初は「json()が壊れてる?」と勘違いしてしまい、原因を探すのに時間がかかりました。
実際には「awaitを書き忘れて、まだ届いていない結果を使おうとしていた」というのが真相でした。
✅ After:await を正しく付ける
async function getUser() {
const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
const data = await response.json(); // 結果を待ってから使う
console.log(data);
}
getUser();
fetchも .json() も、どちらもPromiseを返す処理なので、両方に await を付ける必要がある、と覚えておきましょう。
async関数の外でawaitを使おうとする
もう一つよくあるつまずきが、await を使う場所です。
❌ Before:async関数の外でawaitを書いてしまう
const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
// SyntaxError: await is only valid in async functions
await は、async が付いた関数の中でしか使えません。
いきなりファイルの一番上(トップレベル)で書くとエラーになることがあります。
✅ After:async関数の中に処理をまとめる
async function main() {
const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
const data = await response.json();
console.log(data);
}
main();
「awaitを使いたいときは、まずasync関数を作る」という順番をセットで覚えておくと迷いにくくなります。
fetchで取得したデータを画面に表示する
HTML要素にデータを反映させる
fetchの本当の使いどころは、取得したデータを実際に画面へ表示するところにあります。
<div id="user-name"></div>
async function showUserName() {
const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
const data = await response.json();
const target = document.getElementById("user-name");
target.textContent = data.name;
}
showUserName();
取得したデータの data.name を、textContent を使って画面の要素に反映しています。
外部から取ってきたデータを画面に流し込む、という一連の流れがこれで体感できたかと思います。
通信中であることを意識する
ここで注意したいのは、fetchが完了するまでの間、画面には何も表示されていない時間がある、という点です。
一瞬で終わることも多いですが、通信環境によっては数秒かかることもあります。
「読み込み中です」といった表示を出す方法については、後の記事(ローディング表示の実装)で詳しく扱う予定です。
まずは今回、「データを取得して表示する」という基本の流れをしっかり体に馴染ませておきましょう。
まとめ
この記事のポイント
fetchはブラウザ標準のAPI通信の仕組みで、外部のデータを取得できる- fetchはPromiseを返す非同期処理で、async/awaitを使うと読みやすく書ける
awaitの付け忘れや、async関数の外でのawait使用はよくあるエラーの原因になる- 取得したデータは
.json()で変換してから、textContentなどで画面に反映する
次に読むべき記事
fetchの基本が分かったところで、次は実際に外部APIからデータを取得して、リスト表示するところまで踏み込んでいきます。
→ 次の記事:外部APIからデータを取得して表示する
