見出し画像

非同期処理を理解せよ【async】

ことの発端は、ぼくが非同期処理を覚えては忘れを繰り返していることです。

なんでこの記事を書いたか

もちろん、ぼく自身が忘れないようにするのが一番の理由です。
非同期処理、それをある程度頭の中で体系的に組み立てる必要があると考えています。

だが、同じような境遇の人はおそらくいるのではないかと思います。ということで、今回非同期処理について備忘録を書き残しておこうと思います。


そもそも、同期処理(sync)とは?

プログラムを書いた順に実行して結果を得る処理方法のことです。
つまり、そのプログラムの命令一つ一つを実行し終わってから次に進む方法です。

const addNumber = (nA, nB) => {
  const result = nA + nB;
  return result;
};

const priceApple = 127;
const priceOrange = 55;

const hoge = addNumber(priceApple, priceOrange)

console.log(hoge);

上の例では`const hoge = addNumber(priceApple, priceOrange)`の行を実行してから`console.log(hoge)`が実行されます。
つまり、addNumberが実行されてその完了を待ってからその先に進むと言うことです。

同期処理で何が困るの?

端的に、その命令の実行の間、他の全てのプログラムが停止することです。
もっとシンプルに言うと、実行している間まるでフリーズしているように見えます。これでは操作しているユーザーに不安を与えてしまうかもしれません。

例えば、APIを叩いているときに、そのレスポンスが返ってくるまで他の処理を止めたりすることは適切ではありません。そこで非同期処理として

非同期処理(async)とは?

非同期処理はある命令を実行している間、その最中に他の処理を止めることなく実行できる方式のことです。
他の処理を行っている最中にもその処理を継続して実行させることが可能だということです。

`setTimeout()`関数

最も代表的なものは`setTimeout()`関数だと思われます。これは、第一引数にコールバック関数を、第二引数にミリ秒を指定します。第一引数の内容を第二引数のミリ秒待ってから実行するというものです。実行方法を見てみましょう。

const task = () =>{
  console.log("taskが実行されています");
};

console.log("これからsetTimeoutを実行します");
setTimeout(()=>{
  task();
}, 1000 );
console.log("setTimeoutが実行されました")

実行は、
1. `console.log("これからsetTimeoutを実行します");`
2. `setTimeout()`関数
3. `console.log("setTimeoutが実行されました")`
の順に行われます。

しかし、setTimeout関数は非同期処理なので、上の例だと1000ミリ秒待ってからコールバック関数が実行されます。すなわち、実際のログは1, 3, 2の順番で表示されることになります。
setTimeoutはタイマーをセットするイメージに近いと思います。タイマーをセットして、それが作動したときに思い出して実行し直す、そんな感じに理解するとより理解しやすいのではないでしょうか。

APIを叩くときの非同期処理

実践的には以下のようなときに非同期処理を使うものだと思います。

  • Web APIを叩く

  • データベースにクエリを投げる

このような外部との通信は自分のシステムだけでコントロールできません。すなわち外部の要因によって自分のシステムの停止を招くことは避けなくてはならないということです。
APIを叩くときの実装でよく使われるのがasync、await、Promiseです。この文章はこの三つの使い方をきちんと忘れないようにするのがメインです。

const test = async() => {
  await fetch("https://nantokakantokaapi")
  .then((res)=>{
    console.log(`成功: ${res}`);
  }).catch((err)=>{
    console.log(`失敗: ${err}`);
  })
};

test();

https://nantokakantokaapiというapiにアクセスするとき(実在しません)のコードです。

  • 非同期処理を含む関数やクラスに`async`を記載

  • 実行完了を待つ非同期処理の関数に`await`をつけて呼び出し

これで`await`が付与されているfetch関数が終わるまでその関数はその先には進みません。重要なのは非同期処理なので`test()`関数が終わるのを待たずにその先の処理は実行されます

Promiseオブジェクト

`Promise`とは非同期処理の結果と結果の値を表すオブジェクトです。

Promiseは以下の状態を持っています。

  1. pending: 最初の状態で、成功も失敗もしていない

  2. fulfilled: 処理が成功した状態

  3. rejected: 処理が失敗した状態

fetch APIはPromiseオブジェクトを返す関数です。そして、thenやcatchはPromiseオブジェクトのメソッドです。
それを使うことでそれが行われた際の非同期処理を行わせることができるというわけです。


この記事が気に入ったらサポートをしてみませんか?