プログラミング講座【中級編】第3回:非同期処理とコールバック関数
サマリ
非同期処理とコールバック関数は、モダンなプログラミングにおいて欠かせない概念です。今回は、同期処理と非同期処理の違いから始まり、コールバック関数の仕組みと実践的な使用例までを詳しく解説します。
詳細
同期処理と非同期処理の違い
プログラミングを学び始めたときに最初に習うのは同期処理です。同期処理とは、コードが上から順番に実行されて、前の処理が終わるまで次の処理が開始されない方式です。これは理解しやすく、予測可能な動作をします。
しかし、実際のアプリケーション開発では、同期処理だけでは問題が生じます。例えば、サーバーからのデータ取得やファイルの読み込み、データベースクエリなど、時間がかかる処理を同期的に実行すると、その処理が完了するまでプログラム全体がハングアップしてしまいます。
ここで活躍するのが非同期処理です。非同期処理は、時間がかかる処理を開始した後、その完了を待たずに次の処理に進むことができます。処理が完了したら指定された処理を実行する仕組みになっています。このように、プログラムの応答性を高めることができるのです。
コールバック関数とは
コールバック関数は、他の関数に引数として渡される関数のことです。渡された関数内で、特定の条件を満たしたときや処理が完了したときに呼び出される(コールバックされる)という特徴があります。
非同期処理における実装パターンとしては、時間がかかる処理を実行する関数に、完了後に実行したい処理をコールバック関数として渡します。処理が完了したら、そのコールバック関数が実行される、という流れになります。
JavaScript を例に挙げると、タイマー処理である setTimeout 関数はコールバック関数を使用する典型的な例です。2番目の引数に指定した時間経過後に、第1引数のコールバック関数が実行されます。
コールバック関数の実践例
具体的な使用例として、ファイル読み込み処理を考えてみましょう。Node.js の fs モジュールを使う場合、readFile 関数の最後の引数にコールバック関数を指定します。ファイル読み込みが完了すると、エラー情報とファイルの内容を引数として、このコールバック関数が呼び出されます。
APIからデータを取得する場合も同様です。HTTP リクエストを送信して、サーバーからの応答が返ってきたときに処理を行いたい場合、コールバック関数を使用します。レスポンスの受信完了をきっかけにして、データを処理する関数が実行される仕組みです。
コールバック地獄への注意
コールバック関数を使うことで非同期処理を実装できますが、注意すべき点があります。それが「コールバック地獄」です。
非同期処理が複数重なると、コールバック関数の中にさらにコールバック関数が入り込む構造になります。この入れ子が深くなると、コードが左に深くインデントされていき、可読性が急速に低下します。
このような問題を回避するために、モダン JavaScript では Promise や async/await という新しい仕組みが導入されました。これらは次回以降で詳しく解説する予定ですが、非同期処理のコードをより読みやすく、管理しやすくするための重要な概念です。
コールバック関数を学ぶメリット
Promise や async/await が主流になった現在でも、コールバック関数の理解は重要です。既存のコードにはコールバック関数が多く使われており、レガシーシステムの保守には必須の知識となります。
また、コールバック関数の仕組みを理解することで、非同期処理の基本的な考え方が身につきます。これが後に学ぶ Promise や async/await の概念をより深く理解するための土台になるのです。
まとめ
非同期処理とコールバック関数は、実践的なプログラミングにおいて必ず習得すべき概念です。難しく感じるかもしれませんが、具体例を試しながら丁寧に学んでいけば、必ず理解できます。次回は Promise について学び、さらに非同期処理の世界を深掘りしていきましょう。
