Tech Blog

プログラミングと技術の情報サイト

JavaScriptの非同期処理を完全理解する

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を活用しましょう。

← 記事一覧に戻る