8.2 コールバックによる非同期処理の扱い
ES2015で Promise が導入される以前、非同期処理を扱うための最も原始的かつ一般的な方法は「コールバック関数」によるものでした。
8.2.1 コールバック関数とは
Section titled “8.2.1 コールバック関数とは”コールバック関数とは、非同期処理が終わったときに呼び出される関数のことです。
- 仕組み: 非同期処理を開始する関数に対して、「処理が終了したら呼び出してほしい関数」をあらかじめ引数として渡(登録)しておきます。
- ノンブロッキングな実行: 非同期処理を開始する関数自体は一瞬で終了し、プログラムは即座に次の行へと進みます。その後、裏側での処理が完了したタイミングでコールバック関数が呼び出され、処理の結果が引数として渡されます。
8.2.2 タイマーの例
Section titled “8.2.2 タイマーの例”TypeScript環境(ブラウザやNode.js)で利用できる setTimeout 関数は、一定時間待つという非同期処理を行います。
- 使い方:
setTimeout(コールバック関数, ミリ秒)のように指定します。 - 挙動:
setTimeout自体はタイマーをセットするだけですぐに終了し、プログラムは先に進みます。指定した時間が経過した後に、登録したコールバック関数が呼び出されます。
8.2.3 fsモジュールによるファイル操作の例
Section titled “8.2.3 fsモジュールによるファイル操作の例”Node.jsの fs モジュールが提供する readFile なども、コールバック関数を利用する非同期APIです。
- エラーファーストコールバック: Node.jsのコールバック関数の引数は、原則として 1つ目がエラー(
err)、2つ目が処理結果(result) となります。 - 成功と失敗: 読み込みが成功すれば
errはnullになりresultにデータが入りますが、失敗した場合はerrにErrorオブジェクトが入ります。 - エラーハンドリングの重要性: 同期処理のランタイムエラーとは異なり、非同期処理のエラーはコールバックの引数として渡されるだけなので、無視してしまいがちです。そのため、明示的かつ注意深くエラーハンドリングを行う必要があります。
8.2.4 同期処理と非同期処理の順序
Section titled “8.2.4 同期処理と非同期処理の順序”TypeScript(JavaScript)の実行において極めて重要な原則として、「同期的に実行中のプログラムに非同期処理が割り込むことはない」 というルールがあります。
- 実行の優先度: プログラムがコードを上から下へ順番に実行している最中(同期的な実行中)は、たとえ裏で非同期処理が完了しても、コールバック関数が割り込んで実行されることはありません。
- 待機: 同期的な実行がすべて完了し、CPUが「フリーな状態」になって初めて、完了していた非同期処理のコールバック関数に順番が回ってきて実行されます。