シンプルなJavaScriptやモダンなReactなどを使っていると「データをフェッチする」という言葉を聞いたことがあるかと思います。
結論、外部からデータを取得するという意味になるのですが意外と初学者の方はフェッチを習わずに実務に入っていたりします。
最近ではフェッチ自体にライブラリを使うことが当たり前になったので、どちらかと言うと「ライブラリの使い方を覚える」と言う感じかもしれません。
JavaScriptにはfetch()という関数が用意されていて、こちらの使い方を知っておくとライブラリを使うときの理解が進むかと思います。
fetch()をそのまま使っている現場は少なくなっていますが、仕組みを理解するために一度触ってみましょう。
また動画もあるので必要に応じて活用してください。
JavaScriptにおけるfetchの基本的な使い方
冒頭にフェッチとは外部からデータを取得する行為だと説明しました。
データと言っても色んな種類があって、それぞれで細かく文法が変わりますので何点か例を出しながら解説していきます。
まずはテキストデータを扱うパターンです。
テキストデータです
fetch("test.txt")
.then((data) => data.text())
.then((res) => console.log(res));
// 「テキストデータです」と出力される
fetch関数は引数に取得するデータのパスやURLを指定します。
さらにthenメソッドで繋げてtext()を実行するとテキストデータを文字列に変換します。
thenメソッドで繋げているのは「前の処理を待つ」ことが目的です。
上記のコードの場合だとtest.txtが読み込めていないのにtext()を実行しても意味がないからです。
分かりやすくするためにfetchとは別にコンソールログを追加してみます。
fetch("test.txt")
.then((data) => data.text())
.then((res) => console.log(res));
// ここを追加
console.log("done");
// 「done」が最初に出力される
学習教材やスクールで「プログラムは上から下に向かって順番に実行される」と習ったかと思います。
しかし上記の場合は、下に書いたはずのコンソールログが先に実行されます。
fetch関数にthenメソッドを繋げているため時間がかかっており、その間にconsole.log(“done”)が実行されたわけです。
このように処理を開始するタイミングをコントロールする考え方を「非同期処理」と言って、非同期処理を簡単に理解するための記事を別で公開しているので参考までにどうぞ。
またfetch関数のような非同期処理はJavaScriptの場合、別の書き方で表現するのが最近の傾向としてあるので紹介しておきます。
async function fetchData() {
const data = await fetch("data.json");
const res = await data.json();
console.log(res);
}
fetchData();
こちら先ほどのthenメソッドの部分を書き換えている形です。
「async」がついた関数は自動的に「await」を使うルールになっていて、awaitというのが先ほどで言うところのthenの役割になっています。
書き方こそ違いますが結果は同じになるので両方の書き方に慣れておくことをお勧めします。
// ①thenを使った書き方
fetch("test.txt")
.then((data) => data.text())
.then((res) => console.log(res));
// 「テキストデータです」と出力される
// ②async,awaitを使った書き方
async function fetchData() {
const data = await fetch("data.json");
const res = await data.json();
console.log(res);
}
fetchData();
// 「テキストデータです」と出力される
JavaScriptにおけるfetchでJSONデータを取得する方法
続いてJSONデータをfetchで使う方法です。
{
"id": "0001",
"name": "AAA",
"age": 20
}
fetch("data.json")
.then((data) => data.json())
.then((res) => console.log(res));
// {"id": "0001", "name": "AAA", "age": 20}と出力される
JSONデータの場合はjson()を使うことでデータの中身を読み込んでオブジェクトに変換します。

こちらasync,awaitを使った書き方は以下のようになります。
async function fetchData() {
const data = await fetch("data.json");
console.log(data);
const res = await data.json();
console.log(res);
}
fetchData();
ちなみに「.then」で繋げる書き方をPromiseチェーンと、「async」での書き方をasync/awaitと呼ぶことが多いです。
書き方の違いが大きく出るのがエラー処理を含めたコードを書く時です。
例題としてAPIからJSONデータを取得する処理をエラー処理を含めて、それぞれの書き方で書いてみたいと思います。
まずはPromiseチェーンで書いてみます。
fetch("https://jsonplaceholder.typicode.com/posts")
.then((res) => {
if (!res.ok) {
throw new Error("fetchに失敗しました");
}
return res.json()
})
.then((data) => console.log(data))
.catch((error) => console.error("エラーです:", error));
fetchメソッドで指定したURLに間違いがあった時に備えてエラー処理を追加しました。
Promiseチェーンでのエラー処理は最後に「.catch( )」の中で書くのがルールです。
上記の場合だとfetchメソッドに失敗した場合は「res.ok」がfalseになる想定をしてthenメソッドの中に条件分岐を書きました。
条件分岐に入った時は「”fetchに失敗しました”」というエラー文がcatchメソッドに投げられます。
投げられたエラー文はcatchメソッドの引数で受け取ることで、catchメソッドの中で使用することになります。
結果としてコンソールに「fetchに失敗しました」が表示されるわけです。
続いて同じものをasync/awaitで書き直してみます。
async function fetchFunc() {
try {
const res = await fetch("https://jsonplaceholder.typicode.com/posts");
if (!res.ok) {
throw new Error("fetchに失敗しました");
}
const data = await res.json();
console.log(data);
} catch (error) {
console.error("エラーです:", error);
}
}
fetchFunc();
async/awaitの書き方だとtry catchでエラー処理をします。
tryの中で非同期処理をまとめて書いておき、エラーがあった時の処理をcatchの中に書くルールです。
初学者の方には条件分岐のようなイメージが分かりやすいと思います。
2つの書き方はどちらも正解ですが、async/awaitの方が「throw new Error(“fetchに失敗しました”);」を書く場所に迷いにくいです。
Promiseチェーンで書く方法だと「.then」がどんどん増えていくことで「どのthenメソッドの中にエラー文を書けば良いんだ?」となる可能性が高いです。
熟練されたエンジニアであれば問題ないですが初学者の方には注意でしょう。
2つの書き方を練習しながら実際の開発ではasyc/awaitをメインに書く方が良いかもしれませんね。
またAPI関連でよく出てくるJSONデータというものが初めての方には詳細を解説した記事があるので参考にしてください。
JavaScriptにおけるfetchで画像データを扱う方法
fetchでは画像データを読み込むこともできます。
fetch("../images/image.png")
.then((data) => data.blob())
.then((res) => console.log(res));

画像データの場合はblob()で読み込むのですが、blob()の返り値はオブジェクトになっています。
実際の画面に読み込んだ画像を表示するところまでやってみたいと思います。
まずはHTMLに画像を表示するのに必要なimgタグを新しく作成します。
fetch("../images/image.png")
.then((data) => data.blob())
.then((res) => {
// ここから修正
const image = new Image();
console.log(image);
});

imgタグを作ることができましたね、続いてsrc属性にパスを作成したいと思います。
fetch("../images/image.png")
.then((data) => data.blob())
.then((res) => {
const image = new Image();
// ここから修正
image.src = URL.createObjectURL(res);
console.log(image);
});

src属性を追加することができました、パスのURLは何だか分からない文字列になっていますが先ほど実行したblob()の結果になります。
あとはHTMLに作成したimgタグを挿入するだけです。
fetch("../images/image.png")
.then((data) => data.blob())
.then((res) => {
const image = new Image();
image.src = URL.createObjectURL(res);
// ここを追加
document.body.appendChild(image);
});
ちなみにこちらもasync,awaitを使った書き方も紹介しておきます。
async function fetchImg() {
const data = await fetch("../images/image.png");
const res = await data.blob();
const image = new Image();
image.src = URL.createObjectURL(res);
document.body.appendChild(image);
}
fetchImg();