JavaScriptプログラムに関する各種メモ書き

Promise の then() / catch() / finally() と async await

● Promiseを返す関数の例

  function myPromiseFunc() {
    return new Promise((resolve, reject) => {
      var min = 1;
      var max = 10;
      var result = Math.floor(Math.random() * (max + 1 - min)) + min;
      console.log(result);
      if (result === 1) {
        resolve('Success!')
      }
      else {
        reject("失敗です")
      }
    })
  }

  // 実行
  myPromiseFunc().then((result) => {
    console.log(result)   // 文字列 Success! が返る
  }).catch((error) => {
    console.log(error)    // 文字列 失敗です が返る
  })

● Promise / them() と async await

・ 1. Promiseの状態

pending: 初期状態、実行中。成功も失敗もしていない
fulfilled: 処理が完了した状態。then メソッドを呼び出す
rejected: 処理が失敗した状態。then メソッドと catch メソッドを呼び出す。

Promiseのコンストラクタ
Promiseのコンストラクタは、2つの関数(resolve, reject)を引数に取ります。

・1番目の関数(resolve)に引数を渡して実行すると状態がfulfilledになり、引数の値がPromiseオブジェクトが保持する値になる
・2番目の関数(reject)に引数を渡して実行すると状態がrejectedになり、引数の値がPromiseオブジェクトが保持する値になる
・関数が例外を投げた場合も状態がrejectedになり、投げた値がPromiseオブジェクトが保持する値になる

引用 : https://bit.ly/3TxbKst

・2. Promise の then() / catch() / finally() とは何か?

then()  は、 Promise のインスタンスの状態が fulfilled となったときに実行する関数を登録できるインスタンスメソッドです。
catch()  とは、 Promise のインスタンスの状態が rejected となったときに実行する関数を登録するインスタンスメソッドです。
finally() は、処理が成功しても失敗してもいずれの場合でも最後実行される関数を登録するインスタンスメソッドです。

then() は、以下のように定義されています。

Promise.prototype.then(onFulfilled, onRejected)
onFulfilled : fulfilled の状態のとき(resolve が呼ばれたとき)に実行される関数
onRejected : rejected の状態のとき(reject が呼ばれたとき)に実行される関数

catch() は、以下のように定義されています。

Promise.prototype.catch(onRejected)
onRejected : rejected の状態のとき(reject が呼ばれたとき)に実行される関数

使い方としては今まで try / catch を使っていたような場面で、かわりに await/catch を使います。 https://qiita.com/akameco/items/cc73afcdb5ac5d0774bc

finally() はES2018(ES9) から登場しました

finally() は処理が成功しても失敗してもいずれの場合でも最後実行される関数

● then(f,f) と then(f).catch(f) の違いは何か?

then の最初の関数(fullfilled)で)でエラーを発生させた時に .catch があるとそれを捕捉できる。
import axios from "axios";
axios("/list.json")
  .then(response => {
    const list = response.data;
    if (list.length === 0) {
      return Promise.reject(new Error("Empty list!"));
    }
    return list;
  })
  .catch((err) => {
    console.log(err.name + ': ' + err.message)
  });

実行結果

Error: Empty list! 

https://bit.ly/3D2FeXm

● async とは何か?

非同期関数を定義する関数定義です。
async function で非同期関数を定義できます。
async function は Promise インスタンスを返却します。

async による関数の定義

async function MyFunc() {
  return 'HOGEHOGE';
}

定義した非同期関数の実行

MyFunc()
    .then(value => console.log(value));

● setTimeout を await で使う

function waitSleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms))
}

5秒待つ

await waitSleep(5000)

1行で書くなら

await new Promise(resolve => setTimeout(resolve, 5000)) // 5秒待つ

ealush/wait

https://github.com/ealush/wait

Timers Promises API が最高

https://www.pandanoir.info/entry/2021/04/21/234305

● よくあるエラー(Unexpected reserved word 'await'.)

・async ではない関数内で await している
・Promise を返さないものを await している。

をチェックしましょう

● thenとawaitは両方併用可能

    console.log( '● start' );
    
    await myfuncAsync().then((result) => {
      console.log( result );
    })

    console.log( '● end' );

● async関数内で reject をしたいときは

Promise.reject を使用します

async function foo() {
    await wait(1000);
    return Promise.reject(new Error('Whoops!'));
}

● Javascriptエンジンについて

Node.js / Deno / Google Chrome 内で使われているのは V8
Firefoxで使われているのは SpiderMonkey
Safariで使われているのは JavaScriptCore

です。 JavaScriptエンジンによる違いも認識しておくとさらに良いでしょう

No.2053
12/23 09:46

edit