ryokun Lab.

async/awaitのせいで同期処理と非同期処理が混同している人のための記事。

同期処理、非同期処理がごちゃまぜになる人、async/awaitの使い方がよくわかってない人、非同期処理ってなに?って人向けの記事です。

🐧

こんにちは! JavaScriptを扱うときによく出てくるasync/awaitに関して質問です。

まずは、同期・非同期処理についてそれぞれ簡単に説明してください。 具体例もつけてくれると嬉しいです。

💁‍♂️

こんにちは!JavaScriptのasync/awaitについての質問、承りました。まずは、同期処理と非同期処理について簡単に説明します。

同期処理

同期処理では、命令が順番に一つずつ実行されます。ある命令の処理が終わるまで、次の命令には移りません。例えば、あるデータの計算が終わるまで、次の行のコードは実行されません。

console.log('1番目の処理');
console.log('2番目の処理');
console.log('3番目の処理');

このコードでは、'1番目の処理'が出力された後に'2番目の処理'が出力され、最後に'3番目の処理'が出力されます。

非同期処理

非同期処理では、ある命令がバックグラウンドで実行されている間に、他の命令が同時に実行されます。つまり、ある処理を待っている間にも、他の処理を進めることができます。

console.log('1番目の処理');
setTimeout(() => {
    console.log('2番目の処理');
}, 2000);
console.log('3番目の処理');

このコードでは、'1番目の処理'が出力された後すぐに'3番目の処理'が出力されます。そして、2秒後に'2番目の処理'が出力されます。setTimeout関数が非同期で動作するため、それを待たずに次の命令に移っています。

async/await

async/awaitは、JavaScriptにおいて非同期処理をより読みやすく、直感的に書くための機能です。asyncを関数の前につけることで、その関数は非同期関数になり、awaitを使って非同期処理の完了を待つことができます。

🐧

なるほど〜 ありがとうございます。

非同期処理を記述するときに、"async/await"を使うことがなんとなく、理解できません。

だって、async/awaitを用いると上から順番に処理される、つまり「同期処理」されるわけじゃないですか。

ということで、僕の直感的な理解だと"同期処理を記述する時に"async/awaitを使うという認識の方がしっくりきます。

そのあたりはどういう解釈をすればよいのでしょうか?

💁‍♂️

async/awaitの使用に関するあなたの疑問は非常に良い指摘です。確かに、async/awaitを使うとコードは上から順番に実行されるように見えますが、実際には非同期処理を行っています。ここでのキーポイントは、「非同期処理を同期的な書き方で表現する」という点にあります。

非同期処理の同期的表現

  • 同期処理のような見た目: async/awaitを使用すると、非同期処理が同期処理のように見えます。これは読みやすく、理解しやすいコードになります。
  • 非同期処理の本質: しかし、awaitが使われる場所では、JavaScriptエンジンはその非同期処理が完了するまで待機し、その間に他のタスク(例えばイベントリスナーや他の非同期処理)を実行することができます。つまり、awaitのポイントで非同期処理が行われているのです。

実際の動作

例えば、以下のコードを考えてみましょう。

async function fetchData() {
    console.log('データ取得開始');
    const data = await fetchSomeData(); // ここで非同期処理を待機
    console.log('データ取得完了');
    return data;
}

console.log('データ取得前');
fetchData();
console.log('データ取得後');

このコードでは、以下の順序で処理が行われます:

  1. 「データ取得前」が出力されます。
  2. fetchData関数が呼び出され、'データ取得開始'が出力されます。
  3. fetchSomeData関数の非同期処理が開始されますが、JavaScriptはこの処理を待機させます。
  4. この間に、「データ取得後」が出力されます。
  5. fetchSomeData関数の非同期処理が完了したら、'データ取得完了'が出力され、データが返されます。

結論

async/awaitは、非同期処理をより直感的で読みやすい同期的なコードで書くことを可能にしますが、実際には非同期の動作をしています。これにより、非同期処理の複雑さを抽象化し、よりシンプルなコードを実現できるのです。

🐧

なるほど! つまり、async/awaitは本来、非同期処理で動くはずの処理がを同期処理のように記述することが出来るため、非同期処理で扱うという言い方が正しいということですか?

💁‍♂️

はい、その理解で正しいです。async/awaitは、非同期処理をより読みやすく、同期処理のように見える形で記述するための機能です。そのため、async/awaitは非同期処理で扱うという言い方が適切です。

重要なポイント

  1. 非同期処理を簡素化: async/awaitを使用することで、複雑な非同期コード(例えば、プロミスのチェーン)を、より直感的で読みやすい形で表現できます。
  2. コードの流れの簡潔さ: これにより、コードの流れが同期コードに似た形になり、特に非同期処理が多く含まれるアプリケーションにおいて可読性が向上します。
  3. 非同期の本質を保持: しかし、awaitが使われる場所では、JavaScriptエンジンはその非同期処理の完了を待ちますが、その間に他のタスクを実行することが可能です。これは、非同期処理の本質を保ちつつ、コードの見た目をより理解しやすくしていると言えます。

実用的な例

たとえば、複数の外部APIからデータを取得する場合、async/awaitを使うと、各APIからのレスポンスを順番に処理することができます。それぞれのAPI呼び出しは非同期で行われますが、コードはまるで同期処理のように見え、各ステップが完了するまで順番に進んでいきます。

このように、async/awaitは非同期処理を取り扱う強力なツールであり、JavaScriptでの非同期プログラミングをよりシンプルかつ効率的にするために広く利用されています。

🐧

勉強になりました〜!

最後に、いつもasync/awaitを扱うときに、どっちがどっちかわからなくなるのでおすすめの覚え方というか使い方があれば教えてください。

💁‍♂️

asyncawaitを区別しやすくするための覚え方や使い方をお教えしますね。これらは非常に便利な機能ですが、最初は混同しやすいです。以下のポイントが役立つでしょう。

async

  • 意味: asyncは「非同期」という意味です。これを関数の前に付けると、その関数は非同期関数になります。
  • 覚え方: asyncは「非同期関数の始まり」を示します。つまり、このキーワードを見たら「非同期処理をする関数が始まる」と考えてください。

await

  • 意味: awaitは「待つ」という意味です。これはasync関数内でのみ使われ、非同期処理の完了を待ちます。
  • 覚え方: awaitは「非同期処理を待つ」を示します。つまり、このキーワードを見たら「ここで非同期処理が完了するのを待っている」と考えてください。

使い方のポイント

  1. 関数の宣言時にasyncを使う: 非同期処理を含む関数を作成するときは、関数の定義の始めにasyncを付けます。これにより、その関数は非同期関数になります。
  2. 非同期処理を行う場所でawaitを使う: awaitは、async関数の中でのみ使います。これを使うことで、非同期処理(例えば、APIからのデータ取得)が完了するまで、関数の実行を一時停止(待機)させることができます。

実例

// 非同期関数の宣言(asyncを使う)
async function fetchData() {
    // 非同期処理を待つ(awaitを使う)
    const data = await fetch('<https://example.com/data>');
    return data;
}

// 非同期関数の使用
fetchData().then(data => {
    console.log(data);
});

このように、asyncは関数の「開始」、awaitは関数の「中」で非同期処理を「待つ」ために使われると覚えると、混同しにくくなるでしょう。

🐧

あざす。