非同期JavaScript:API通信とモジュールの導入スライド
非同期JavaScript:API通信とモジュール - 同期と非同期
書いた順に出ない行がある
JavaScript は書いた行を上から順に実行します。ところが作品データを取りに行く処理は返事が来るまで数百ミリ秒かかるので、その間ずっと画面を止めるわけにいきません。そこで「予約だけして先に進む」という進め方が出てきます。
上から順に片づけるのが同期、予約して先へ進むのが非同期です。次の図解で、この差が待ち時間にどう効くのかを見ます。
真ん中に書いた行の出力が、いちばん最後に回っています。
console.log("取得を始めます");
setTimeout(() => {
console.log("作品データが届きました");
}, 500);
console.log("次の描画に進みます");
// 取得を始めます
// 次の描画に進みます
// 作品データが届きました1 / 4
非同期JavaScript:API通信とモジュール - 同期と非同期
待ち時間がどこまで縮むのか
注文の数を増やして、上段と下段の合計時間を見くらべてください。
- 上段の同期は棒が階段状にずれて始まり、合計は各注文の足し算になる
- 下段の非同期は棒が全部左端からそろい、合計はいちばん長い1本ぶんで止まる
- トグルを入れて依存を作ると、非同期でも棒がずれて合計が同期と同じに戻る
2 / 4
考えてみよう外しても進めます
作品データの取得を非同期にすれば、どんな場合でも待ち時間は短くなると思いますか。
選ぶと、この枚の中で答えと理由を確かめられます。
3 / 4
非同期JavaScript:API通信とモジュール - 同期と非同期
コールバックだけで組むと横に伸びる
非同期の結果を受け取る昔ながらのやり方が、関数を先に渡しておいて終わったら呼んでもらうコールバックです。取得が3段続くと、次の処理が前の処理の内側に入り込みます。
この階段を上から下へ読める形に戻すために作られたのが Promise です。次のレッスンで自分の手で作ります。
3段でこの深さです。失敗したときの分岐を足すと、さらに増えます。
loadWorks((works) => {
loadDetail(works[0].id, (detail) => {
loadTags(detail.id, (tags) => {
render(detail, tags);
});
});
});4 / 4
非同期JavaScript:API通信とモジュール - Promise をつくって返す
あとで値が入る箱を作る
Promise は、いまはまだ決まっていない値をあとで受け取るための箱です。new Promise に渡した関数の中で resolve を呼ぶと、その時点で箱の中身が決まります。
中身を取り出すには、箱が埋まるのを待つ必要があります。その待ち方が await です。
作った直後の箱を覗いても、まだ中身は決まっていません。
const works = new Promise((resolve) => {
setTimeout(() => resolve(["レシピ検索アプリ"]), 300);
});
console.log(works); // Promise { <pending> }1 / 4
箱を返す関数にして、await で開ける
作った箱をそのまま return すると、呼び出した側は await で中身を受け取れます。作品データの取得を、この1往復の形にまとめます。
new Promiseあとで値が入る箱resolve([{ title: "レシピ検索アプリ" }])箱に値を入れるawait fetchWorks()箱を開けて中身を取る実行の流れ
| 経過 | そこで起きること |
|---|---|
| 0ms | fetchWorks() が呼ばれ、まだ空の箱が返る |
| 0ms | await がその行で中身を待ち始める |
| 300ms | resolve が呼ばれ、箱に配列が入る |
| 300ms | await の行に配列が返り、次の行へ進む |
resolve が呼ばれるまで、await の次の行は動きません。
箱を作って返す側と、await で開ける側。この2つがそろうと非同期処理が1本つながります。
2 / 4
考えてみよう外しても進めます
resolve も reject も一度も呼ばない Promise を await すると、どうなると思いますか。
選ぶと、この枚の中で答えと理由を確かめられます。
3 / 4
非同期JavaScript:API通信とモジュール - Promise をつくって返す
箱が取りうる3つの状態
executor で何を呼ぶかを切り替えて、箱の状態と await の行がどう変わるかを見てください。
- resolve を呼べば fulfilled、reject を呼べば rejected。決まり方は2通りだけ
- 何も呼ばなければ pending のまま。await した行から先へ進まない
- 2回目の resolve は無視される。決着は1回きりなので、同じ Promise を何度 await しても返ってくる値は同じ
4 / 4
非同期JavaScript:API通信とモジュール - async と await
async を付けた関数は Promise を返す
関数の頭に async を付けると、その関数の戻り値は必ず Promise になります。文字列を return しても、受け取る側に届くのは中身が文字列の箱です。
async を付けた関数の中では await が使えます。中身を取り出すのはその await の役目です。
return したのは文字列ですが、返ってきたのは箱のほうです。
async function loadTitle() {
return "レシピ検索アプリ";
}
const returned = loadTitle();
console.log(returned instanceof Promise); // true1 / 4
前の結果を次の呼び出しに渡す
await は Promise の中身が届くまでその行で待ちます。届いた値をそのまま次の行で使えるので、コールバックの入れ子が上から下へ並ぶ形になります。
await fetchWorks()一覧が届くまで待つworks[0].id前の結果を次に渡すreturn { title: detail.title, tags }この戻り値も Promise になる呼び出しの順
| 段 | 待つもの | 次に渡すもの |
|---|---|---|
| 1 | fetchWorks | works[0].id |
| 2 | fetchDetail | detail.id |
| 3 | fetchTags | まとめて return |
3段の入れ子が、上から順に読める3行になりました。
この直列の形が要るのは、前の段の結果を次で使うときだけです。関係の無い取得まで並べると、待ち時間が足し算になります。
2 / 4
考えてみよう外しても進めます
works.forEach(async (w) => { await save(w); }); と書いた次の行で console.log("完了") を出すと、保存が全部終わってから出ますか。
選ぶと、この枚の中で答えと理由を確かめられます。
3 / 4
非同期JavaScript:API通信とモジュール - async と await
待ち方の早見
await をどこに書くかで、待つ範囲が変わります。よく使う4つの形を先に押さえておくと、書き分けで迷いません。
forEach の中の await は外側を待たせません。順番が要るなら for...of に置き換えます。
| やりたいこと | 書き方 |
|---|---|
| Promise の中身を待つ | const works = await fetchWorks() |
| await を使える関数にする | async function loadPortfolio() |
| 配列を1件ずつ順に待つ | for (const w of works) { await save(w) } |
| まとめて始めて全部待つ | await Promise.all([...]) |
| 終わりを見届けない | await を書かずに呼ぶだけ |
4 / 4
非同期JavaScript:API通信とモジュール - Promise.all で同時に待つ
関係の無い取得まで順番待ちさせている
作品一覧・プロフィール・タグ一覧は、どれも互いの結果を使いません。それでも await を3行並べると、1つ目が終わるまで2つ目は始まらず、待ち時間が足し算になります。
3つとも先に始めてしまい、全部そろうまで1回だけ待つ。それを1行で書けるのが Promise.all です。
どれも前の行の結果を使っていないのに、順番に待っています。
const works = await fetchWorks(); // 400ms
const profile = await fetchProfile(); // 300ms
const tags = await fetchTags(); // 200ms
// ここに届くまで 900ms かかっている1 / 4
まとめて始めて、1回だけ待つ
Promise.all には Promise の配列を渡します。3つの呼び出しは配列を組み立てる時点でもう動き出していて、Promise.all はそれが全部そろうのを1回で待つ役です。
Promise.all全部そろうまで待つ[works, profile, tags]渡した配列と同じ順で返るfetchWorks()この行で3つとも動き出す待ち時間の比較
| 書き方 | fetchWorks | fetchProfile | fetchTags | 合計 |
|---|---|---|---|---|
| await を3行並べる | 400ms | 300ms | 200ms | 900ms |
| Promise.all にまとめる | 400ms | 300ms | 200ms | 400ms |
同時に始めるので、合計はいちばん遅い 400ms のぶんで済みます。
縮むのは、3つが互いの結果を使っていないからです。前の結果が要る呼び出しは、この配列に入れられません。
2 / 4
考えてみよう外しても進めます
Promise.all([fetchWorks(), fetchProfile(), fetchTags()]) で fetchTags がいちばん先に終わったとき、返ってくる配列の並びはどうなりますか。
選ぶと、この枚の中で答えと理由を確かめられます。
3 / 4
非同期JavaScript:API通信とモジュール - Promise.all で同時に待つ
まとめて待つときの選び分け
並べて待つ書き方は Promise.all だけではありません。失敗したときにどうしたいかで、使うものが変わります。
Promise.all は1つでも失敗した時点で例外になり、他の結果は受け取れません。失敗した1件だけ諦めて残りを描きたいときは allSettled を使います。
| やりたいこと | 書き方 |
|---|---|
| 全部の成功を待つ | Promise.all([...]) |
| 失敗も含めて全件の結果を見る | Promise.allSettled([...]) |
| いちばん早い1つだけ使う | Promise.race([...]) |
| 前の結果を次に使う | await を順に並べる |
4 / 4
非同期JavaScript:API通信とモジュール - 非同期のエラーを捕まえる
失敗を伝えるのは throw
async 関数の中で throw すると、その関数が返す Promise は失敗した状態になります。fetch はサーバーがエラーを返しても失敗扱いにしないので、状態を自分で見て投げます。
投げる側はこれで済みます。受け止める側を次の枚で書きます。
通信が届いても中身が 500 のことがあるので、res.ok を見てから投げます。
async function fetchWorks() {
const res = await fetch("/api/works");
if (!res.ok) {
throw new Error("作品データを取得できませんでした");
}
return res.json();
}1 / 4
await した行を try で囲む
失敗した Promise は await した行で例外になります。第6章で使った try と catch がそのまま効くので、成功でも失敗でも同じ形の値を返すようにまとめます。
await fetchWorks()ここで例外が飛ぶcatch (error)同期のときと同じ受け止め方return { ok: false, works: [] }失敗でも同じ形で返す呼び出し側が受け取る値
| 起きたこと | 戻ってくる値 |
|---|---|
| 作品データを取得できた | { ok: true, works: [...] } |
| サーバーが 500 を返した | { ok: false, works: [] } |
| 通信そのものが切れた | { ok: false, works: [] } |
どの場合も ok と works の2つが返るので、呼び出し側の書き方は1通りで済みます。
失敗のときだけ undefined を返すと、呼び出し側で毎回そのチェックが要ります。形をそろえておくほうが後が楽です。
2 / 4
考えてみよう外しても進めます
try の中で await を書き忘れて const works = fetchWorks(); としたとき、fetchWorks の中の throw は catch で受け止められますか。
選ぶと、この枚の中で答えと理由を確かめられます。
3 / 4
エラーを取りこぼさないための早見
例外がどこへ届くかは、await をどこに書いたかで決まります。取りこぼしが起きやすい形を先に並べておきます。
try の中で await する
catch に届く
await を書かずに呼ぶ
catch に届かず未処理になる
Promise.all を await する
最初に失敗した1件が catch に届く
forEach の中で await する
外側の catch には届かない
finally を付ける
成功でも失敗でも通る。読み込み表示の解除に使う
受け止め方そのものは同期のときと変わりません。違うのは、await を書いた行が例外の出口になるという1点だけです。
4 / 4
非同期JavaScript:API通信とモジュール - HTTP と REST の読みかた
ブラウザとサーバーは 1 往復で話す
画面にデータが出るまでの通信は、頼む文と返ってくる文の 1 往復でできています。行きに書くのは「どの方法で、どこの何が欲しいか」の 1 行だけ、帰ってくるのは番号と中身です。この形が分かると、うまくいかないときに行きと帰りのどちらが崩れているかを切り分けられます。
この 1 往復がどこで止まりうるのかを、次の枚で 1 区間ずつ進めて確かめます。
上の 2 行が行き、空行をはさんだ下の 2 行が帰りです。
GET /course-api/works.json HTTP/1.1
Host: yumesaku.tech
HTTP/1.1 200 OK
Content-Type: application/json1 / 5
非同期JavaScript:API通信とモジュール - HTTP と REST の読みかた
1 区間ずつ進めて止まる場所を見る
止める場所を切り替えながら、区間を 1 つずつ進めてください。
- 正常のときは 4 区間そろってはじめて画面が出る。3 区間目までは何も表示されない
- DNS 停止にすると 1 区間目で止まり、住所が分からないので出発すらできない
- サーバ停止にすると 3 区間目まで進む。住所は分かっているのに応答だけが返らない
2 / 5
考えてみよう外しても進めます
ブラウザに「サーバが見つかりません」と出ました。1 往復のどこまで進んでいるでしょうか。
選ぶと、この枚の中で答えと理由を確かめられます。
3 / 5
帰りの中身は、サーバーの中で組み立てられる
行きに出すのは 1 行だけですが、その 1 行を受け取ったサーバーは、どの処理に渡すかを決めてから、データベースに問い合わせて中身を作ります。帰ってくる JSON は最初からどこかに置いてあるのではありません。
フロントエンド
fetch で頼む
GET /works を送って、返事を待つ
サーバーサイド
どの処理か決める
URL とメソッドの組から、担当する処理を選ぶ
JSON を組み立てる
取り出したデータを、返す形に整える
データベース
作品データ
問い合わせに合う行だけを返す
うまくいかないときは、この3つのどこで止まったのかを先に分けます。返ってきた番号が 404 ならサーバーには届いていて、担当する処理が見つからなかった、という所まで絞れます。
4 / 5
非同期JavaScript:API通信とモジュール - HTTP と REST の読みかた
URL とメソッドの付けかたをそろえる
REST は、扱う対象を URL で表し、その対象に何をするかをメソッドで表す決めごとです。名前の付け方を人ごとに変えないための取り決めなので、覚えることは対応表 1 枚しかありません。
URL には名詞だけを書き、動きはメソッドで表します。/getWorks のような URL を作らなくて済むのがこの決めごとの効きどころです。
| やりたいこと | メソッドと URL |
|---|---|
| 作品の一覧が欲しい | GET /works |
| 12 番の作品 1 件が欲しい | GET /works/12 |
| 作品を新しく登録する | POST /works |
| 12 番の作品を書き換える | PUT /works/12 |
| 12 番の作品を消す | DELETE /works/12 |
5 / 5
非同期JavaScript:API通信とモジュール - fetch でデータを取る
待つ場所が 2 回ある
fetch を呼ぶと、まず返事の入れ物が返ってきます。その入れ物にはまだ中身が入っていないので、もう一度待って本文を取り出します。await を 2 回書くのは、届くタイミングが 2 段になっているからです。
送っている中身と返ってくる中身が、それぞれどんな形をしているのかを次の枚で見ます。
1 行目で入れ物が届き、2 行目でようやく中身が取り出せます。
const res = await fetch("https://yumesaku.tech/course-api/profile.json");
const profile = await res.json();
console.log(profile.name); // "山田 結"1 / 4
非同期JavaScript:API通信とモジュール - fetch でデータを取る
送る中身と返る中身を見る
max_tokens のスライダーを下げてから、system を消すトグルを入れてください。
- 送っているのは入れ子の箱でしかない。model と max_tokens と messages が並んでいるだけ
- max_tokens を 5 まで下げると応答が文の途中で切れる。それでもエラーは出ず、stop_reason だけが変わる
- system を消すと口調の指示ごと消えて、返ってくる文の言い方が変わる
2 / 4
考えてみよう外しても進めます
fetch の返り値を res に入れて res.name と書くと undefined になります。なぜでしょうか。
選ぶと、この枚の中で答えと理由を確かめられます。
3 / 4
取り出した値を画面に置く
本文がオブジェクトになってしまえば、あとは今までどおりです。キーで値を取り出して、それぞれの要素の textContent に入れるだけになります。
await res.json()本文を取り出すprofile.roleキーで指すskills.join(" / ")配列は文字列に直す画面に出るもの
| 受け取ったキー | 画面に出る文字 |
|---|---|
| name | 山田 結 |
| role | フロントエンドエンジニア |
| skills | HTML / CSS / JavaScript |
囲った行だけが配列です。そのまま入れると要素がカンマでつながるので、join で区切りを決めています。
取ってくる所と画面に出す所は、はっきり分かれています。次のレッスンでは、この右側を一覧の形に広げます。
4 / 4
非同期JavaScript:API通信とモジュール - 取ったデータを描画する
返ってくるのは配列
1 件ぶんのオブジェクトではなく、作品が並んだ配列が返ってきます。配列なら length で件数が取れますし、map で 1 件ずつ HTML に変えられます。ここから先は今まで書いてきた配列の操作がそのまま使えます。
取ってくるまでには少し時間がかかります。その間に画面に何が出ているのかを、次の枚で並べます。
配列に変わった時点で、外から来たデータだということは忘れて構いません。
const res = await fetch("https://yumesaku.tech/course-api/works.json");
const works = await res.json();
console.log(works.length); // 3
console.log(works[0].title); // "夜の図書館"1 / 4
待っている間と、そろったあと
取ってくる処理は一瞬では終わりません。先に「読み込み中です」を入れておき、配列が届いたところで一覧と件数に差し替えます。差し替える順番を決めておくと、途中で空白の画面が出ません。
読み込み中です先に置いておく.map((w) => "<li>" + w.title + "</li>")1 件を 1 行に変えるworks.length件数はここから画面の移り変わり
| 処理の段階 | 画面に出ているもの |
|---|---|
| fetch を呼んだ直後 | 読み込み中です |
| res が返ってきた | 読み込み中です |
| res.json() が終わった | 作品 3 件と一覧 |
真ん中の行でもまだ差し替わりません。中身が取り出せるのは 3 行目からです。
map が作るのは文字列の配列です。join で 1 本につないでから innerHTML に入れます。
2 / 4
考えてみよう外しても進めます
作品が 1 件も無い配列が返ってきたとき、この書き方だと画面には何が出るでしょうか。
選ぶと、この枚の中で答えと理由を確かめられます。
3 / 4
非同期JavaScript:API通信とモジュール - 取ったデータを描画する
一覧を描くときの手札
やっていることは、配列を文字列に変えて 1 か所に入れるだけです。よく使う書き方を先にまとめておくと、作品でも記事でも同じ形で書けます。
sort は元の配列を書き換えるので、slice で写しを作ってから並べ替えます。取ってきたデータをそのまま壊さずに済みます。
| やりたいこと | 書き方 |
|---|---|
| 1 件を 1 行の HTML に変える | works.map((w) => ...) |
| 配列を 1 本の文字列にする | .join("") |
| 件数を出す | works.length |
| 0 件のときの案内を出す | works.length === 0 で分ける |
| 並べ替えてから描く | works.slice().sort(...) |
4 / 4
非同期JavaScript:API通信とモジュール - response.ok と失敗時の表示
失敗しても fetch は成功する
ここがいちばん引っかかる所です。サーバーが 404 や 500 を返しても、fetch から見れば「返事はちゃんと届いた」ので成功として扱われます。エラーとして投げられるのは、回線が切れていて返事そのものが届かなかったときだけです。
成功と失敗を分ける仕事は、書いた人がやることになります。次の枚でその分け方を見ます。
500 が返っても catch には入りません。自分で res.ok を見に行きます。
const res = await fetch("https://yumesaku.tech/course-api/works-500.json");
console.log(res.status); // 500
console.log(res.ok); // false1 / 4
res.ok で先に分岐する
本文を取り出す前に res.ok を見ます。false なら番号を添えた案内を出して、そこで処理を打ち切ります。ok が true のときだけ json に進むので、失敗した返事を無理に読もうとせずに済みます。
!res.ok200 番台かどうかres.status番号をそのまま見せるawait res.json()ok のときだけ進む返ってきた番号ごとの結果
| status | res.ok | 画面に出るもの |
|---|---|---|
| 200 | true | 3 件 |
| 404 | false | 取得に失敗しました (404) |
| 500 | false | 取得に失敗しました (500) |
| 返事が届かない | 見に行けない | catch のほうに入る |
取り消し線の行だけが catch の担当です。上の 3 行は全部 fetch としては成功しています。
res.ok は status が 200 番台かどうかを表す真偽値です。番号を自分で範囲判定しなくてよいように用意されています。
2 / 4
考えてみよう外しても進めます
500 を返す URL を fetch して try の中に置いたとき、catch のブロックは動くでしょうか。
選ぶと、この枚の中で答えと理由を確かめられます。
3 / 4
失敗の種類ごとに置く場所を決める
失敗といっても原因はいくつかあります。どこで受け止めるかを先に決めておくと、利用者に出す文言もそろいます。
URL が間違っていて 404
res.ok が false になる
サーバー側が落ちて 500
res.ok が false になる
回線が切れて返事が来ない
catch に入る
本文が JSON になっていない
res.json() で catch に入る
受け止めたあとは、画面の要素に書き出して利用者へ知らせます。console だけに書くと、利用者には固まったようにしか見えません。
4 / 4
非同期JavaScript:API通信とモジュール - POST のリクエストを組み立てる
送るときに決めることは 4 つ
取ってくるだけなら URL だけで済みますが、送るときは 4 つを一組で決めます。どこへ送るか、どういう扱いにするか、中身の形は何か、そして中身そのものです。この 4 つがそろって 1 本のリクエストになります。
この 4 つのうち、値が実際どこに載るのかを次の枚で見比べます。
送信そのものはこのコースでは扱いません。組み立てる所までを覚えます。
const endpoint = "https://yumesaku.tech/course-api/works.json";
const options = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title: "夜の図書館", year: 2025 }),
};1 / 4
非同期JavaScript:API通信とモジュール - POST のリクエストを組み立てる
GET と POST で値の載る場所を見比べる
送り方を GET と POST で押し替えたあと、履歴とアクセスログのトグルを入れてください。
- GET はアドレスバーに ?user= から先がそのまま出る。下のボディは空のまま
- POST に替えるとアドレスバーが短くなり、同じ値がボディのほうへ移る
- トグルを入れると、GET のときだけパスワードの残り先が 3 つ並ぶ
2 / 4
考えてみよう外しても進めます
body にオブジェクトをそのまま書いて送ると、サーバーには何が届くでしょうか。
選ぶと、この枚の中で答えと理由を確かめられます。
3 / 4
非同期JavaScript:API通信とモジュール - POST のリクエストを組み立てる
4 つの部品の早見
書き方さえ決まってしまえば、送るデータが変わっても形は同じです。どの部品が何を決めているのかで覚えます。
Content-Type と body の形は必ず合わせます。JSON だと伝えておきながら別の形を送ると、サーバー側で読めません。
| 決めること | 書く場所 |
|---|---|
| どこへ送るか | fetch の第 1 引数の URL |
| どう扱ってほしいか | method。省略すると GET |
| 中身の形は何か | headers の Content-Type |
| 送る中身そのもの | body。文字列で渡す |
| オブジェクトを文字列にする | JSON.stringify(obj) |
4 / 4
非同期JavaScript:API通信とモジュール - ファイルを分けるという考えかた
1 本の app.js が長くなってきたら
取ってくる処理と、整える処理と、画面を組み立てる処理が 1 つのファイルに混ざると、直したい行を探すだけで時間がかかります。役割ごとにファイルを分けて、外から使ってほしいものにだけ export を付けます。
付けなかったものはそのファイルの中だけで生きます。どこまで見せるかを自分で決められる、というのがこの仕組みの本体です。
export を付けた関数だけが、外のファイルから見えるようになります。
// format.js
export function formatYear(year) {
return year + " 年";
}1 / 4
出す側と受け取る側を並べる
外に出す側には export を書き、使う側には import を書きます。使う側から見ると、どのファイルの何を借りているのかが 1 行目にそろいます。
{ formatYear }借りるものの名前"./format.js"どのファイルからfetchWorks()中身は api.js にある3 つのファイルの持ち場
| ファイル | 外に出しているもの | 受け取り方 |
|---|---|---|
| format.js | formatYear | import { formatYear } |
| api.js | fetchWorks | import { fetchWorks } |
| app.js | 何も出さない | 組み立てるだけ |
囲った行が入口のファイルです。入口は借りるだけで、外には何も出しません。
分ける基準は行数ではなく役割です。整える処理と取ってくる処理は、直す理由が別なので分けます。
2 / 4
考えてみよう外しても進めます
import 文の行き先を "./format" と書いて拡張子を省くと、ブラウザではどうなるでしょうか。
選ぶと、この枚の中で答えと理由を確かめられます。
3 / 4
非同期JavaScript:API通信とモジュール - ファイルを分けるという考えかた
書き方と、この教材で動かない理由
書き方そのものは短く覚えられます。ただし、このコースのプレビューでは実際に走らせられません。読み込みの決まりを満たせない場所で動いているからです。
module として読み込むには、そのファイルがどこの生成元のものかが決まっている必要があります。プレビューの枠にはその生成元が無いので、書き方だけを覚えて、実際の分割は自分の手元のプロジェクトで試します。
| やること | 書き方と決まり |
|---|---|
| 外に出す | 出したいものに export を付ける |
| 受け取る | import { 名前 } from "./file.js" |
| 読み込む側の指定 | script タグに type="module" |
| 行き先の書き方 | 拡張子まで書く。./ も省けない |
| この教材で走らせられない理由 | プレビューが生成元を持たないサンドボックスだから |
4 / 4
非同期JavaScript:API通信とモジュール - named export と default export
名前を付けて出すか、1 つだけ代表として出すか
外に出す方法は 2 つあります。名前を付けて何個でも出す named export と、そのファイルの代表を 1 つだけ出す default export です。同じファイルに両方を書くこともできます。
出し方が違うと、受け取る側の書き方も変わります。次の枚で並べて見ます。
上の 2 つが named、いちばん下が default です。default は 1 ファイルに 1 つだけ書けます。
// format.js
export const UNIT = "年";
export function formatYear(year) {
return year + UNIT;
}
export default function formatTitle(work) {
return work.title + " (" + work.year + ")";
}1 / 4
受け取る側の書き分け
named は名前で受けるので波かっこで囲みます。default は名前で選ばないので、波かっこを付けず、受け取る側で好きな名前を付けられます。名前がぶつかるときは as で替えます。
import formatTitle,default は名前を自分で決める{ formatYear as toYear }named は名前で受けて as で替える2 つの出し方
| 出し方 | 出す側の書き方 | 1 ファイルに何個 |
|---|---|---|
| named export | export function f() | 何個でも |
| default export | export default function f() | 1 つだけ |
| 名前を替える | import { f as g } | 受け取る側で決める |
囲った行だけが 1 個に限られます。代表が 2 つあると、どちらを指しているのか決まらないからです。
default は名前が固定されないので、読む人によって呼び名が変わります。名前をそろえたいものは named にしておくと迷いません。
2 / 4
考えてみよう外しても進めます
default export された formatTitle を import { formatTitle } from "./format.js" と書いて受け取るとどうなるでしょうか。
選ぶと、この枚の中で答えと理由を確かめられます。
3 / 4
非同期JavaScript:API通信とモジュール - named export と default export
どちらで出すかの決めかた
迷ったら named にしておけば困りません。default は「このファイルといえばこれ」と言い切れるものが 1 つだけあるときに使います。
まとめて受け取ると fmt.formatYear のように書けます。どのファイルから来た関数なのかが呼び出す所でも分かるので、借りるものが多いときに向いています。
| 出したいもの | 向いている出し方 |
|---|---|
| 小さな関数をいくつも | named export |
| 定数をまとめて | named export |
| そのファイルの代表になるもの | default export |
| 名前がほかとぶつかる | import { f as g } で替える |
| 全部まとめて受け取る | import * as fmt from "./format.js" |
4 / 4
