コールバック: 非同期の基礎

関数を引数として渡す。Promise の前身。

コールバック
後で呼び出される関数。
コールバック地獄
ネストが深くなる問題。
エラーファースト
Node.js の慣例。第1引数がエラー。

コールバック

リレーのバトン (Relay Baton)

コールバックは「走り終わったら渡すバトン(関数)」です。「走り終わったら(処理完了後)、このバトンを持って次の走者(コールバック関数)が走ってね」と依頼します。バトンを渡し続けるとリレー(処理)が繋がります。

JavaScript はシングルスレッドなので、重い処理(ファイル読み込みや通信)で止まらないように、「終わったらこれやって」と関数を予約します。これがコールバックです。しかし、予約が連鎖すると「コールバック地獄」になりがちです。

Callback Basics
// コールバック = 関数を引数として渡す
function greet(name, callback) {
console.log(`Hello, ${name}!`);
callback();
}
greet('Alice', () => {
console.log('Greeting complete!');
});
// 配列メソッドでのコールバック
const numbers = [1, 2, 3, 4, 5];
numbers.forEach((n) => console.log(n));
const doubled = numbers.map((n) => n * 2);
const evens = numbers.filter((n) => n % 2 === 0);
Bad
// ❌ Bad: コールバック地獄
getData((data) => {
processData(data, (result) => {
saveData(result, (response) => {
// ネストが深すぎる
});
});
});
Good
// ✅ Good: Promise/async で平坦に
const data = await getData();
const result = await processData(data);
const response = await saveData(result);

パターン

Events, setTimeout, Error-first
// イベントリスナー(コールバック)
button.addEventListener('click', (event) => {
console.log('Clicked!', event.target);
});
// setTimeout / setInterval
setTimeout(() => {
console.log('1秒後');
}, 1000);
const id = setInterval(() => {
console.log('毎秒');
}, 1000);
clearInterval(id); // 停止
// エラーファーストコールバック (Node.js スタイル)
function readFile(path, callback) {
// callback(error, data)
}
readFile('file.txt', (err, data) => {
if (err) {
console.error('Error:', err);
return;
}
console.log(data);
});
Tip: 新規コードは async/await を使う。コールバックは既存コードの理解用。

合格ライン

コールバックを渡せる
コールバック地獄の問題を説明できる

演習課題

課題1: コールバック
コールバックを引数として渡す関数を作成してください。
課題2: Error-first
Error-first パターンでエラーハンドリングしてください。