【JavaScript】 Promiseと非同期処理を理解する

image

Version

  • Node.js v16.16.0

はじめに

非同期処理がなかなか理解できなかったので、コードと一緒に理解できるようにする。

同期処理と非同期処理の処理の順番

以下のコードを走らせるとどのような結果になるか。nodeで実行してみる。

setTimeout(() => {console.log(1)},1000)
console.log(2);
setTimeout(() => {console.log(3)},0)
console.log(4);
setTimeout(() => {console.log(5)},1000)
console.log(6);
setTimeout(() => {
    console.log(7);
    setTimeout(() => {
        console.log(8);       
    },1000)
},2000)

結果

2
4
6
3
1
5
7
8

表示順は2,4,6,3がすぐに表示され、その1秒後に1,5が表示され、その1秒後に7が表示され、その1秒後に8が表示されます。
同期処理と非同期処理は、まず同期処理が優先して処理されます。その処理が終わった後に非同期処理が実行されます。console.log(1)console.log(5)は同時に動きます。このあたり自分は1秒ずつずれて動くと勘違いしてました。
これをずらして動かすためには、 setTimeout()関数の中にsetTime()関数を入れ込む(callbackする)必要があります。7,8でcallbackをさせています。
*top画面のイメージを参考にしてください。

callbackを使って、カウントダウンをする

上のcallbackを使って、カウントダウンするコードを書くと以下のようになります。

setTimeout(() => {
  console.log(3);
  setTimeout(() => {
    console.log(2);
    setTimeout(() => {
      console.log(1);
    }, 1000);
  }, 1000);
}, 1000);

結果

3
2
1

これは、可読性が悪くコードの管理も難しいということでコールバック地獄とかよく呼ばれています。 こうしたコールバック地獄を避けるためにPromiseがあります。

Promiseを使って、カウントダウンをする

まずはコードを書きます。結果は同じです。

new Promise((resolve) => {
  setTimeout(() => {
    console.log(3);
    resolve();
  }, 1000);
})
  .then(() => {
    return new Promise((resolve) => {
      setTimeout(() => {
        console.log(2);
        resolve();
      }, 1000);
    });
  })
  .then(() => {
    return new Promise((resolve) => {
      setTimeout(() => {
        console.log(1);
        resolve();
      }, 1000);
    });
  });
 

Promiseオブジェクトは第1引数にresolve、第2引数にrejectを指定でき、resolve()させるとthen以下の関数が実行され、reject()させるとcatch以下の関数を実行させることができます。これにより非同期処理の可読性が高まり、またthencatchにより複雑な処理も可能になりました。
上記のコードの場合、resolve()により、then以下で独立してPromiseが動いています。
前のコードより複雑化したように思うかもしれませんが、メインテナンスはやりやすくなったのではと思います。

async/await を使って、カウントダウンをする

最後にasync/awaitを使って書き直します。

func = async () => {
  // 関数に対してasyncと宣言する => この関数は非同期関数
  await log(3);
  await log(2);
  await log(1); // 関数の呼び出しの前にawait => Promiseの結果がくるまで待つ
};

log = (num) => {
  // Promiseを返す関数
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(num);
      resolve();
    }, 1000);
  });
};

func();

functionの前にasyncをつけると、非同期処理を実行できる関数を定義できる。
awaitasyncで定義された関数の中で使う。 log関数は、setTime()を使った待機処理関数をPromiseでラップしたもので、resolve()で結果を返す。 これをawaitの後で、実行するとPromiseでthenを使って実行させたことをthenなしで実行させることができるようになりました。

最後に

async/awaitは、コードはシンプルになるが、裏でPromiseが動いているので、そこを理解しないといけないなと思いました。
いろいろなコードを書きながら非同期処理の理解を深めていきたい。

参考

https://qiita.com/cheez921/items/41b744e4e002b966391a
https://knowledge.sakura.ad.jp/24890/
https://rightcode.co.jp/blog/information-technology/javascript-async-await
小学生でもわかるasync/await/Promise入門【JavaScript講座】

お知らせ

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。

Read More
U30可茂ITインターンハッカソン

U30可茂ITインターンハッカソン

12月28,29日開催。2日間でアプリ開発の企画から完成までを目指す!U30可茂ITインターンハッカソンを開催します。

Read More

タグ

Flutter (110)初心者向け (28)イベント (18)Google Apps Script (15)Nextjs (12)可茂IT塾 (8)Firebase (7)riverpod (6)React (6)ChatGPT (5)vscode (5)デザイン (5)新卒 (4)就活 (4)Figma (4)Dart (4)JavaScript (4)お知らせ (4)FlutterWeb (3)Prisma (3)NestJS (3)Slack (3)TypeScript (3)ワーケーション (3)インターン (3)設計 (2)線型計画法 (2)事例 (2)Git (2)Image (2)File (2)Material Design (2)画像 (2)iOS (2)アプリ開発 (2)React Hooks (2)tailwindcss (2)社会人 (2)大学生 (2)RSS (1)Google (1)Web (1)CodeRunner (1)個人開発 (1)Android (1)Unity (1)WebView (1)Twitter (1)フルリモート (1)TextScaler (1)textScaleFactor (1)学生向け (1)supabase (1)Java (1)Spring Boot (1)shell script (1)正規表現 (1)パワーポイント (1)趣味 (1)モンスターボール (1)CSS (1)SCSS (1)Cupertino (1)ListView (1)就活浪人 (1)既卒 (1)保守性 (1)iPad (1)シェアハウス (1)スクレイピング (1)PageView (1)画面遷移 (1)flutter_hooks (1)Gmail (1)GoogleWorkspace (1)ShaderMask (1)google map (1)Google Places API (1)GCPコンソール (1)Google_ML_Kit (1)Vercel (1)Google Domains (1)DeepLeaning (1)深層学習 (1)Google Colab (1)コード生成 (1)GitHub Copilot (1)オンラインオフィス (1)オブジェクト指向 (1)クラスの継承 (1)ポリモーフィズム (1)LINE (1)Bitcoin (1)bitFlyer (1)コミュニティー (1)文系エンジニア (1)Freezed (1)permission_handler (1)flutter_local_notifications (1)markdown (1)GlobalKey (1)ValueKey (1)Key (1)アイコン (1)go_router (1)debug (1)datetime_picker (1)Apple Store Connect (1)FlutterGen (1)デバッグ (1)Widget Inspector (1)検索機能 (1)Shader (1)Navigator (1)メール送信 (1)Firebase App Distribution (1)Fastlane (1)Dio (1)CustomClipper (1)ClipPath (1)カスタム認証 (1)アニメーション (1)Arduino (1)ESP32 (1)経験談 (1)フリーランス (1)mac (1)csv (1)docker (1)GithubActions (1)Dialog (1)BI (1)LifeHack (1)ショートカット (1)Chrome (1)高校生 (1)キャリア教育 (1)非同期処理 (1)生体認証 (1)BackdropFilter (1)レビュー (1)getAuth (1)Algolia (1)コンサルティング (1)Symbol (1)

お知らせ

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!

可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。

Read More
U30可茂ITインターンハッカソン

U30可茂ITインターンハッカソン

12月28,29日開催。2日間でアプリ開発の企画から完成までを目指す!U30可茂ITインターンハッカソンを開催します。

Read More