全体像:Web API は「JavaScript の外にいる助っ人」
まず前提から整理します。
ブラウザの中で JavaScript が動くとき、
- JavaScript エンジン(言語そのものを実行する脳みそ)
- Web API(ブラウザが提供する「いろんな便利機能」の窓口)
- イベントループとタスクキュー(「あとでやる処理」を管理する仕組み)
が、一緒に仕事をしています。
このうち Web API は「JavaScript ではできないことを、ブラウザが代わりに請け負うための入り口」 です。
非同期処理の文脈では特に、
- 時間がかかる処理(タイマー・通信・DOM イベント)を、JavaScript 本体から切り離して担当する
- 終わったら「これ実行していいよ」とコールバックをキューに積む
という役割を担っています。
ここが重要です。
JavaScript はシングルスレッドで 1 本しかありませんが、
Web API が「外で待つ・外で仕事をする」を担当してくれるからこそ、JavaScript はブロッキングせずに済む、という構造になっています。
Web API って具体的に何を指しているのか
JavaScript の「組み込み」ではなく、ブラウザ側が提供している機能
setTimeout, fetch, DOM(document, window), addEventListener, localStorage など、
ブラウザ環境で使える多くの機能は「言語仕様(ECMAScript)」ではなく「Web API」として定義されています。
例えば、次のコードを見てください。
setTimeout(() => {
console.log("3秒後");
}, 3000);
JavaScriptここで setTimeout 自体は JavaScript のコア言語の一部ではなく、
ブラウザ(や Node.js)が「タイマー機能の API」として提供しているものです。
JavaScript エンジンは、
「3秒待つ」
「待っている間、他の処理を続ける」
といったことは自前ではできません。
「○ミリ秒後にこれ実行して」と Web API に依頼し、
あとは結果が返ってくるのを待つだけ です。
Web API のざっくりした担当範囲
代表的なものだけ挙げると、Web API はこんな領域を担当しています。
- タイマー(
setTimeout,setInterval) - DOM 操作とイベント(
document,addEventListenerなど) - XHR / fetch(ネットワーク通信)
- Web Storage(
localStorage,sessionStorage) - Web Workers(別スレッド)
- その他:Geolocation, WebSocket, Canvas, Audio/Video などたくさん
非同期処理の基礎では、主に
「タイマー」「イベント」「ネットワーク」という 3 つが登場します。
具体例1:setTimeout と Web API(「待つ」の担当を外に出す)
まずコードから動きを追う
console.log("A: start");
setTimeout(() => {
console.log("B: 2秒後の処理");
}, 2000);
console.log("C: end");
JavaScript実行すると、出力はこうなります。
A: start
C: end
B: 2秒後の処理
このとき「中で何が起きているか」を分解してみます。
裏側で起きていること(ざっくり)
- JavaScript エンジンが
"A: start"を実行 setTimeoutを呼ぶ- 「2秒後にこのコールバックを実行して」と Web API(タイマー機能)に依頼
- ここまでで JavaScript の仕事は一旦終わり。コールスタックからは
setTimeoutの呼び出しが消える
- JavaScript はすぐ次に進み、
"C: end"を実行 - 一方、ブラウザ内部のタイマー機構(Web API)が、2秒間カウントダウン
JavaScript のメインスレッドはこの間も他の仕事ができる - 2秒経ったら、Web API が「コールバックをタスクキューに積む」
- イベントループが「メインスレッドが空いたタイミング」で、そのコールバックを実行
"B: 2秒後の処理"が出力される
ここが重要です。
「2秒待つ」のは Web API の仕事であって、JavaScript 本体は「待ち続けている」わけではない。
だから、待ち時間のあいだも UI イベントや他の処理を進められるのです。
具体例2:fetch と Web API(ネットワークも「外注」している)
コードと実行順
console.log("1: リクエスト前");
fetch("https://example.com/data.json")
.then((response) => response.json())
.then((data) => {
console.log("3: データ取得", data);
});
console.log("2: 他の処理");
JavaScript出力の順番は
1: リクエスト前
2: 他の処理
3: データ取得
のようになります。
裏側での流れ
"1: リクエスト前"を出力fetchを呼び出す- JavaScript エンジンは、「この URL に HTTP リクエストを送って、結果が来たら教えて」と Web API に依頼
- このとき、実際のネットワーク通信はブラウザ側の機能(Web API)が担当
fetchはすぐにPromiseを返し、JavaScript の処理は先に進む
"2: 他の処理"を出力- ネットワークの結果が返ってきたら、Web API が「この Promise を解決しなさい」とエンジンに知らせる
実際には、「thenに渡したコールバック」をタスクキュー(正確にはマイクロタスクキュー)に積む - イベントループがそれを実行し、
"3: データ取得"が出力される
ここでのポイントも同じです。
ネットワークの「送信」や「待機」は JavaScript の外(Web API)で行われる。
JavaScript は「依頼をしたらすぐ次に進む」「結果が来たときだけコールバックで受け取る」役割に徹しています。
具体例3:DOM イベントと Web API(「ユーザーの操作監視」担当)
イベントリスナーの動き
const button = document.querySelector("#btn");
button.addEventListener("click", () => {
console.log("ボタンがクリックされました");
});
JavaScriptこのコードを書いた時点では、まだ何も起きません。
ボタンが押されたときに初めて "ボタンがクリックされました" が出力されます。
裏側では誰が「クリックされたこと」を検知しているか
addEventListenerを呼ぶと、「この要素にクリックイベントが来たら、この関数を呼んで」という情報が Web API 側に登録される- その後、ユーザーがボタンをクリックすると、ブラウザのネイティブコードがそれを検知
- 「クリックが起きた」というイベントが Web API 層からタスクキューに渡される
- イベントループがそれを拾い、メインスレッドでコールバック(無名関数)を実行
"ボタンがクリックされました"が出力される
ここが重要です。
ユーザーの操作(クリック、スクロール、キー入力など)を「監視し続けている」のは JavaScript 本体ではなく、ブラウザのネイティブ部分=Web API 側。
JavaScript は「イベントが発生したら呼ばれるコールバックを登録しておく」だけです。
なぜ Web API が非同期処理でそんなに重要なのか
JavaScript は「できること」が限られているから
ECMAScript(言語仕様)としての JavaScript は、本質的には
- 変数・関数・クラス
- 配列やオブジェクト
- 数学演算や文字列操作
のような「計算」のための機能に集中しています。
一方、実際のアプリ開発では、
- 時間を測る
- ファイルやネットワークにアクセスする
- ユーザー操作を受け取る
- 画面を描画する
といった「外側の世界」とのやりとりが必要です。
これらは、JavaScript 単体ではどうにもできません。
だからこそ、ブラウザ(や Node.js)が ホスト環境として Web API を提供し、外側との橋渡しをしている わけです。
シングルスレッドでも「止まらない」ための鍵になっている
もし JavaScript 自身が
- 3秒間待つ(タイマー)
- サーバーの返事を待つ(ネットワーク)
- ユーザーのクリックを延々待つ(イベントループ)
といったことをすべて自前でやっていたら、
その待ち時間のあいだ、メインスレッドは完全にブロックされてしまいます。
実際には、
- 待つ・監視する → Web API
- 結果が出たら「この処理を実行して」とタスクキューに依頼 → イベントループが拾ってメインスレッドで実行
という分業をすることで、
「シングルスレッドだけどノンブロッキング」 な実行モデルを成立させています。
ここが重要です。
非同期処理の大枠は、
JavaScript 本体は「依頼」と「結果を受け取る処理」だけ書く。
その間の「待つ」「外の世界とやりとりする」は Web API が担当する。
という役割分担だ、と理解しておくとスッキリします。
まとめ:Web API の役割を一言でいうと
Web API の役割を一文でまとめると、
「ブラウザやホスト環境が持っている機能(タイマー・ネットワーク・DOM・イベントなど)を、JavaScript から使えるようにし、時間のかかる処理を JavaScript の外側で引き受ける窓口」
です。
押さえておきたいポイントは次の通りです。
JavaScript エンジンは計算担当で、タイマー・通信・イベント監視などは Web API が担当している。setTimeout や fetch は「待つ」のではなく、「Web API に依頼して、結果が来たらコールバックをキューに積んでもらう」仕組み。
DOM イベントも、ユーザーの操作を検知しているのはブラウザ側(Web API)で、JavaScript はコールバック登録だけする。
この分業のおかげで、JavaScript はシングルスレッドなのに、待ち時間中もブロックされずに他の処理を続けられる。
これを前提として、
- コールスタック(今どこを実行中か)
- タスクキュー(あとで実行する処理の待ち行列)
- イベントループ(キューから仕事を持ってくる係)
の話を重ねていくと、「JavaScript の非同期モデル」が一本の線でつながってきます。
まずは、
setTimeoutfetchaddEventListener
あたりについて、「これは JavaScript そのものじゃなくて Web API 側の機能なんだ」と意識しながらコードを書いてみてください。
それだけで、非同期処理の見え方がかなり変わってくるはずです。
