この記事について
この記事は、生成AIを活用した自動生成フローで作成しています。ECMAScript 2026のPromise仕様、Microsoft LearnのTask非同期プログラミング、VBAのDoEvents公式資料を確認し、似て見える言葉を役割別に整理しています。検証ステータス:🧪 言語仕様・公式資料確認済み・Node.jsでCallback/Promise/awaitの実行順を確認済み
同期・非同期・Callback・Promiseは何が違う? ― 「待ち方」と「結果の受け取り方」を分ける
同期・非同期は処理をどう待つかという性質です。CallbackやPromiseは、処理の完了や結果を扱うための代表的な書き方・仕組みです。したがって、非同期 = Promise ではありません。
さらに、VBAの DoEvents も非同期処理そのものではありません。実行をいったんOSへ渡して、キューにあるイベントを処理させる仕組みです。
まず言葉を別の軸に置く
| 用語 | 何を表すか | よくある誤解 |
|---|---|---|
| 同期 | 呼び出した処理の進行と待ち方 | 「遅い処理」の意味ではない |
| 非同期 | 完了待ちの間に呼び出し側をブロックしない構成など | 並列処理と同義ではない |
| Callback | 後で呼ぶ関数を渡すパターン | Callbackなら必ず非同期、ではない |
| Promise | 将来得られる結果を表すオブジェクト | Promise自体が別スレッドを作るわけではない |
| async/await | 非同期処理を扱いやすく記述する言語機能・構文 | await すると必ずスレッドが増える、ではない |
| DoEvents | OSへ制御を渡しイベントを処理させるVBA機能 | 一般的な非同期APIではない |
同期と非同期は時間軸で見る
sequenceDiagram
participant C as Caller
participant W as Work
rect rgb(245,245,245)
Note over C,W: 同期のイメージ
C->>W: start
W-->>C: result
C->>C: 次の処理
end
rect rgb(245,245,245)
Note over C,W: 非同期のイメージ
C->>W: start
W-->>C: 完了を待つための表現
C->>C: 待ち方に応じて別の処理へ
W-->>C: completion / result
end
非同期の価値は「3秒かかる処理を1秒にする」ことではありません。I/O待ちの間にUIを固めない、別の処理を進める、複数の操作を構成しやすくする、といった待ち時間の扱い方にあります。
Callbackは「関数を渡す」考え方
Callbackは、処理がある条件に達したとき呼び出してほしい関数を渡すパターンです。イベント処理にも使えますし、同期的なAPIでもCallbackという形は使えます。
そのため「Callbackがあるから非同期」と判断するのではなく、実際のAPIがいつ・どこでCallbackを呼ぶかを確認します。
Promiseは将来の結果を表す
ECMAScript 2026仕様ではPromiseを、遅延された、そして場合によっては非同期の計算の最終結果を表すplaceholderとして定義しています。Promiseには pending、fulfilled、rejected という状態があります。
ここで重要なのは「Promise = 並列実行装置」ではないことです。Promiseは結果と状態を扱いやすくする抽象化であり、実際の作業がどのスレッドやランタイム機構で進むかは別問題です。
async/awaitは読みやすさを変える
.NETのTask-based Asynchronous Patternでは、await を使うことで、非同期処理を上から順に読むコードに近い形で書けます。await は待機中に現在のスレッドを単純にブロックするためのものではありません。
つまり、Callback、Promise、Task、async/awaitは「非同期という性質をどう表現し、結果をどう受け取るか」の選択肢です。
VBAのDoEventsは何が違う?
MicrosoftのVBA公式資料では、DoEvents はOSへ制御を渡し、イベントキューの処理後に制御が戻る関数です。長いループの途中でExcelのUIイベントを処理させる用途などがあります。
ただし、DoEventsを呼んだから処理が非同期APIへ変わるわけではありません。また、イベント処理中に同じ処理が再入すると予期しない結果になる可能性があるため、公式資料も再入に注意を促しています。
すぐ試す:実行順をconsoleで観察する
言葉だけだと混ざりやすいので、外部APIを使わない小さなJavaScriptで見比べます。ブラウザのDeveloper ToolsのConsoleへ貼るか、Node.jsで実行できます。
console.log("A: 同期 start");
setTimeout(() => {
console.log("D: Callbackの結果");
}, 200);
Promise.resolve("Promiseの結果").then((result) => {
console.log("C:", result);
});
console.log("B: 同期 end");
ポイントは、setTimeout やPromiseの完了を待っている間も、まず現在の同期処理が B まで進むことです。
ただし、この短い例だけを見て「Promiseは別スレッド」「Callbackは必ず非同期」と一般化してはいけません。Callbackは同期的に呼ばれるAPIにも使えますし、Promise自体がthreadを作るわけでもありません。
もう少し分かりやすく、同期 → Callback → Promise → async/await を同じファイルで比較する完全版をGitHubに置きました。
node demo.js
迷ったら2つ質問する
この処理は完了まで呼び出し元をどう待たせるのか?
完了結果はCallback、Promise、Task、イベントなど何で返ってくるのか?
この2軸に分けると、VBA、PowerShell、JavaScript、C#で名前が違っても整理しやすくなります。
