JavaScript, Node.js, 非同期処理におけるPromise.allとforEach
Promise.all と forEach は、JavaScriptとNode.jsの非同期処理において、複数の操作を並列または逐次的に実行するための重要なツールです。
Promise.all
- いずれかが拒否された場合は、すぐに拒否され、他のPromiseの結果は無視されます。
- すべてが解決された場合は、すべての結果を含む配列を返します。
- 複数のPromiseを同時に実行し、すべてが解決または拒否されるまで待機します。
例
const promises = [
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2'),
fetch('https://api.example.com/data3')
];
Promise.a ll(promises)
.then(responses => {
// すべてのPromiseが解決された場合の処理
responses.forEach(response => {
response.json().then(data => {
console.log(data);
});
});
})
.catch(error => {
// いずれかのPromiseが拒否された場合の処理
console.error(error);
});
forEach
- forEach自体がPromiseを返しません。
- 関数は非同期操作を行う場合、Promiseを返しても構いません。
- 配列の各要素に対して指定された関数を呼び出します。
const data = [1, 2, 3];
data.forEach(item => {
setTimeout(() => {
console.log(item * 2);
}, 1000);
});
Promise.allとforEachの使い分け
- 逐次処理が必要な場合
forEachを使用します。 - 並列処理が必要な場合
Promise.allを使用します。
注意
- forEachは、各要素に対して関数を呼び出すため、時間がかかっても処理が継続されます。
- Promise.allは、すべてのPromiseが解決されるまで待機するため、時間がかかる場合があります。
const promises = [
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2'),
fetch('https://api.example.com/data3')
];
Promise.a ll(promises)
.then(responses => {
// すべてのPromiseが解決された場合の処理
responses.forEach(response => {
response.json().then(data => {
console.log(data);
});
});
})
.catch(error => {
// いずれかのPromiseが拒否された場合の処理
console.error(error);
});
解説
- 複数のPromiseを作成
fetch
関数を使用して、3つのURLからデータを取得するPromiseを作成します。 - Promise.allを実行
Promise.all
関数にPromiseの配列を渡します。 - すべてのPromiseが解決された場合
then
メソッドで、すべてのPromiseが解決された場合の処理を指定します。 - 各Promiseの結果を処理
forEach
メソッドを使用して、各Promiseの結果を処理します。
const data = [1, 2, 3];
data.forEach(item => {
setTimeout(() => {
console.log(item * 2);
}, 1000);
});
- 配列を作成
data
という配列に数値を格納します。 - forEachを実行
forEach
メソッドを使用して、配列の各要素に対して関数を呼び出します。 - 非同期処理
setTimeout
関数を使用して、1秒後に数値を2倍して出力する非同期処理を実行します。
Async/Await
- Promiseの代わりに使用でき、コードがより読みやすくなります。
- 非同期処理を同期的なコードのように記述できる構文です。
async function fetchData() {
const [response1, response2, response3] = await Promise.all([
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2'),
fetch('https://api.example.com/data3')
]);
const [ data1, data2, data3] = await Promise.all([
response1.json(),
response2.json(),
response3.json()
]);
console.log(data1, data2, data3);
}
fetchData();
- 競合的な処理やタイムアウトを実装する際に便利です。
- 複数のPromiseのうち、最初に解決または拒否されたものを返すPromiseを返します。
const promise1 = new Promise((resolve) => {
setTimeout(resolve, 2000, 'Promise 1');
});
const promise2 = new Promise((resolve) => {
setTimeout(resolve, 1000, 'Promise 2');
});
Promise.race([promise1, promise2])
.then( result => {
console.log(re sult); // 'Promise 2'
});
- すべてが拒否された場合は、AggregateErrorを投げます。
const promise1 = new Promise((resolve) => {
setTimeout(resolve, 2000, 'Promise 1');
});
const promise2 = new Promise((resolve) => {
setTimeout(resolve, 1000, 'Promise 2');
});
const promise3 = new Promise((_, reject) => {
setTimeout(reject, 3000, 'Promise 3');
});
Promise.any([promise1, promise2, promise3])
.then(result => {
console.log(result); // 'Promise 2'
})
.catch(error => {
console.error(error); // AggregateError: All promises were rejected.
});
javascript node.js asynchronous