JavaScriptの非同期処理を完全理解する
JavaScriptはシングルスレッドで動作しますが、非同期処理によってブロッキングなしに 複数の処理を効率よく扱うことができます。コールバック、Promise、async/awaitの 3つのアプローチを順番に理解することが重要です。
コールバック地獄の問題
初期のJavaScriptは非同期処理をコールバック関数で扱っていましたが、ネストが深くなる問題がありました。
fs.readFile('a.txt', (err, data1) => {
fs.readFile('b.txt', (err, data2) => {
fs.readFile('c.txt', (err, data3) => {
// ネストが深くて読みにくい
});
});
});
Promiseによる改善
fetch('/api/user')
.then(res => res.json())
.then(user => fetch(`/api/posts?userId=${user.id}`))
.then(res => res.json())
.then(posts => console.log(posts))
.catch(err => console.error(err));
async/awaitで同期的に書く
async function loadUserPosts() {
try {
const res = await fetch('/api/user');
const user = await res.json();
const postsRes = await fetch(`/api/posts?userId=${user.id}`);
const posts = await postsRes.json();
return posts;
} catch (err) {
console.error(err);
}
}
並列実行でパフォーマンスを上げる
独立した非同期処理は Promise.all で並列実行するとレスポンスが速くなります。
const [user, config] = await Promise.all([
fetch('/api/user').then(r => r.json()),
fetch('/api/config').then(r => r.json()),
]);
まとめ
async/awaitは内部的にPromiseを使っているため、Promiseの理解が前提になります。 エラーハンドリングはtry/catchで統一し、並列化できる処理はPromise.allを活用しましょう。