Node.js Promise.all 並列処理解説
「Node.jsのPromise.allは並列処理なのか、それとも逐次処理なのか?」の日本語解説
Node.jsにおけるPromise.allは、並列処理(concurrent processing)を行います。
Promise.allの役割
並列処理の仕組み
Node.jsのイベントループと非同期処理の特性により、Promise.allは複数のPromiseを同時に実行することが可能です。つまり、複数のPromiseが並行して処理され、それぞれのPromiseが解決されると、その結果がPromise.allに返されます。
具体的な例
const promise1 = new Promise((resolve) => {
setTimeout(() => {
resolve('Promise 1');
}, 1000);
});
const promise2 = new Promise((resolve) => {
setTimeout(() => {
resolve('Promise 2');
}, 2000);
});
P romise.all([promise1, promise2])
.then((results) => {
console.log(results); // Output: ['Promise 1', 'Promise 2']
})
.catch((error) => {
console.error(erro r);
});
この例では、promise1
とpromise2
の両方が同時に実行され、それぞれ1秒と2秒後に解決されます。Promise.allはこれらのPromiseがすべて解決されるまで待機し、その後、両方の結果を配列として返します。
注意
- I/Oバウンドなタスク
Promise.allは特にI/Oバウンドなタスク(ファイル読み込み、ネットワーク通信など)の並列処理に効果的です。CPUバウンドなタスク(複雑な計算など)の場合は、並列処理による性能向上効果が限られることがあります。 - 並列処理と同時処理の違い
並列処理は複数のタスクが同時に実行されることを指し、同時処理は複数のタスクが同時に実行されるように見えることを指します。Node.jsのイベントループの仕組みにより、並列処理が実現されますが、実際には、複数のタスクが高速に切り替えられて実行されているため、同時処理のように見えます。
Node.jsのPromise.all並列処理の例コード解説
Node.jsのPromise.allは、複数のPromiseを並列に処理します。
基本的な例
const promise1 = new Promise((resolve) => {
setTimeout(() => {
resolve('Promise 1');
}, 1000);
});
const promise2 = new Promise((resolve) => {
setTimeout(() => {
resolve('Promise 2');
}, 2000);
});
P romise.all([promise1, promise2])
.then((results) => {
console.log(results); // Output: ['Promise 1', 'Promise 2']
})
.catch((error) => {
console.error(erro r);
});
解説
promise1
とpromise2
はそれぞれ1秒と2秒後に解決されるPromiseです。Promise.all
はこれらのPromiseを並列に実行します。- 両方のPromiseが解決されると、
then
コールバックが実行され、結果が配列として出力されます。
I/Oバウンドなタスクの例
const fs = require('fs');
const promise1 = new Promise((resolve, reject) => {
fs.readFile('file1.txt', 'utf8', (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
const promise2 = new Promise((resolve, reject) => {
fs.readFile('file2.txt', 'utf8', (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
Promise.all([promise1, promise2])
.then((results) => {
console.log(results); // Output: ['内容 of file1.txt', '内容 of file2.txt']
})
.catch((error) => {
console.error(error);
});
promise1
とpromise2
はファイル読み込みの操作を実行するPromiseです。- Promise.allはこれらのPromiseを並列に実行し、両方のファイル読み込みが完了すると、結果を配列として出力します。
複数のPromiseの処理
const promises = [
new Promise((resolve) => setTimeout(() => resolve('Promise 1'), 1000)),
new Promise((resolve) => setTimeout(() => resolve('Promise 2'), 2000)),
new Promise((resolve) => setTimeout(() => resolve('Promise 3'), 30 00)),
];
Promise.all(promises)
.then((results) => {
console.log(results); // Output: ['Promise 1', 'Promise 2', 'Promise 3']
})
.catch((error) => {
console.error(error);
});
promises
配列に複数のPromiseを格納します。- Promise.allはこれらのPromiseをすべて並列に処理し、結果を配列として出力します。
async/awaitを使用する
- 例
- 利点
- より簡潔で読みやすいコードが書ける。
- エラー処理が容易。
async function processPromises() {
const promise1 = new Promise((resolve) => {
setTimeout(() => {
resolve('Promise 1');
}, 1000);
});
const promise2 = new Promise((resolve) => {
setTimeout(() => {
resolve('Pro mise 2');
}, 2000);
});
const results = await Promise.all([promise1, promise2]);
console.log(results); // Output: ['Promise 1', 'Promise 2']
}
processPromises();
Promise.raceを使用する
- 利点
Promise.race([
new Promise((resolve) => setTimeout(() => resolve('Promise 1'), 1000)),
new Promise((resolve) => setTimeout(() => resolve('Promise 2'), 2000)),
])
.then((result) => {
console.log(result); // Output: 'Promise 1'
})
.catch((error) => {
console.error(error);
});
手動でPromiseを管理する
- 利点
- より細かい制御が可能。
const promise1 = new Promise((resolve) => {
setTimeout(() => {
resolve('Promise 1');
}, 1000);
});
const promise2 = new Promise((resolve) => {
setTimeout(() => {
resolve('Promise 2');
}, 2000);
});
P romise.resolve()
.then(() => promise1)
.then((result1) => {
console.log(result1); // Output: 'Promise 1'
return promise2;
})
.then((result2) => {
console.log(result2); // Output: 'Promise 2'
})
.catch((error) => {
console.error(error);
});
ライブラリを使用する
- 例
- Bluebird
- Q
- 利点
javascript node.js promise