35
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

非同期処理の歴史とasync await/promiseを居酒屋のノリで理解する

Last updated at Posted at 2021-08-31

#本記事の内容
本記事は、非同期処理に関して纏めた記事となります。
また、検証ツール(macですとoption + command + I で起動)を用いることでどなたでもすぐに実感できるかと思います。
非同期処理って何?まあなんとなく使えてるしいいや、PromiseとかAsyncとかよくわからんし後でいいや〜、書いてるけど実はあまり意味わかってないんですよね〜、って方向けに書いております。
筆者自身の備忘録的な要素も兼ねておりますので、間違い等ありましたら、お手数ですが、ご指摘いただけますと幸いです。
よろしくお願いします。

#非同期処理とは
通常、プログラムは上から順に処理を実行する。すなわち、一番上に時間のかかる処理を書いていると、その処理より下に書かれている処理に時間がかかってしまい、何も実行/表示されない

(店員:最初に揚げ物のオーダー処理してると、いきなり時間かかっちゃうからお客さん待たせちゃうな...どうしよう???)

バックグラウンドで処理を行うこととした。

→先に画面を表示させ、データを取得するなど、時間を要する処理に関しては実行され次第、画面に表示させれば良い!
(他のオーダーで先に出せそうなもの先に出しちゃえ!生ビールとトマトときゅうりは先出しちゃえ!)

この様に、処理を一度バックグラウンドに移すことを非同期処理という。
処理のタイミングをずらしてやるイメージ。
(処理1、2、3とあった際に、2は時間がかかる...先に1と3をやっちゃって2は終わったら表示すればいいや!)

#非同期処理をどうやって実現しているのか
コールバック関数で実現した。(他の関数の引数として使用される関数)
以下の例でいうところのconsole.log(1)がコールバック関数。

setTimeout(()=>console.log(1),1000);
console.log(2)
//上の2行をデベロッパーツールに書いて、エンターキーを押してみてください。

//以下出力結果
2
undefined
1

#地獄の始まり
上記でコールバック関数を利用することによって、非同期処理を行うことができる様になったが、ここで問題点が出てくる。
バックグラウンドでの処理が増えるほど、記述がややこしくなってしまった...
例えば、以下の例を考えてほしい。
以下のイメージ。

〜〜〜失敗例〜〜〜
setTimeout(()=>console.log(3),1000);
setTimeout(()=>console.log(2),1000);
setTimeout(()=>console.log(1),1000);

//出力結果
3
2
1
//と同じタイミングで出力される。
//〜〜〜成功例〜〜〜
setTimeout(()=>{
 console.log('生中お待ち!')
   setTimeout(()=>{
    console.log('トマト!お待ち')
      setTimeout(()=>{
        console.log('ヘイよ唐揚げ!')
       },1000)
  },1000)
},1000)

失敗例の場合はは、全てが同じタイミングでで処理されてしまう。。。
成功例ではうまく処理できているものの、たった三つの処理でこの記述量、、、ネストされててミスしそうだし、、、これがいくつもあると考えると...
(オーダーがこれだからいいものの、もっとオーダーされたらそもそも覚えらんねえ...)

#promiseの発明

連続した非同期書をフラットに書くことができる。
promiseオブジェクトを作る→resolveすると次の処理に行ける→.thenで次の処理を書く。
入れ子にせんで良くなりました!
以下、例です。

new Promise (resolve=> resolve('生中お待ち!'))
.then(res=>console.log(res))
// ここでのresは`response`の略。

じゃあ、先程の居酒屋での処理を下に記述します。

new Promise(resolve=>{
   setTimeout(()=>{
      console.log('生中お待ち!')
       resolve()
    },1000)
   }).then(()=>{
      return new Promise(resolve=>{
        setTimeout(()=>{
         console.log('トマト!お待ち');
         resolve();
        },1000);
       });
     }).then(()=>{
        return new Promise(resolve => {
           setTimeout(() => {
             console.log('ヘイよ唐揚げ!')
             resolve()
          },1000)
       })
      })

ネストがなくなり、順番に出てきますけど、、、全然見にくくない???
さっきまでは、オーダーを頭で覚えてたけど、今度は紙に書いて順番に並べてもらった!!!!!、、、結局たくさんオーダー貰ったら見にくいよ...
もっといい方法ないかね...???

#aync await
asyncを宣言することによって、関数が非同期処理であることを明示する。

func = async () =>{
await log ('生中お待ち!');
await log ('トマト!お待ち');
await log ('ヘイよ唐揚げ!');
};

log=(order)=>{
return new Promise (resolve=>{
   setTimeout(()=>{
        console.log(order);
        resolve();
   },1000)
 });
}
func()

同じ処理(皿を出したり、調味料を準備したりはもうあらかじめやっておいて、具体的なオーダーが入ったらその都度やることをやっていく!)
これで一気に見やすく、かつ楽に記述できるようになったのではないだろうか???

#最後に
だいぶ分かりにくかったかもしれません。
分かりにくい方は、当記事の内容に関しては多くの方が記事等に残してくださってますので、そちらをご覧になると良いかもしれません。
最後までお付き合いいただき、ありがとうございました.

35
32
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?