1. TOPTOP
  2. Webサービス
  3. JavaScript

GoogleのFirebaseで学習するECMAScript6のPromiseオブジェクト・thenメソッド・catchメソッド

ecmascript6_promise_object

db.collection("users").add({
    first: "Ada",
    last: "Lovelace",
    born: 1815
})
.then(function(docRef) {
    console.log("Document written with ID: ", docRef.id);
})
.catch(function(error) {
    console.error("Error adding document: ", error);
});

Cloud Firestoreを使ってみる(新しいタブで開く)」というページを見ていると、このようなコードが出てきます。

Promiseオブジェクト・thenメソッド・catchメソッド

1."users"という名前にCollectionにDocumentを追加する(Promiseオブジェクト)
2.成功したら"Document written with ID: "の文字列とID番号が表示される(thenメソッド)
3.失敗したら"Document written with ID: "の文字列とエラーが表示される(catchメソッド)

直感的にスクリプトとを読むとこのような意味になります。1、2、3行目ともにECMAScript6より取り入れられた新しい記法です。

1.Promiseオブジェクト

例示したスクリプトには”Promise”という文字列は用いられていません。ただFirebaseの公式ドキュメント(新しいタブで開く)を読む限り、dbオブジェクトはPromiseの概念が用いられています。

var db = new Promise(function(resolve, reject) { ... });

おそらくfirebase-app.jsかfirebase-firestore.jsのどちらかで、Promiseオブジェクトをインスタンス化されていると推察されます。

一般にPromiseは、非同期処理を実行し、それが終了するまで次の処理を遅延させるために使われます。FirebaseではPromiseが関数のライフサイクルを確実に実行させる性質を利用して、長時間実行される関数や無限にループする関数からの過剰な課金を避けるようにしています。

コールバック地獄とFirebase

function sleep(callback) {
        setTimeout(function() {
            callback();
        }, 1000);
    }

    sleep(function() {
      console.log("番号!");
      sleep(function() {
        console.log("一");
        sleep(function() {
          console.log("二");
          sleep(function() {
            console.log("三");
          });
        });
      });
    });

ECMAScript6のPromiseオブジェクトが登場する以前は、JavaScriptで非同期処理を順番どおりに実行させるためには、いわゆる「コールバック地獄」となるスクリプトを書く必要がありました。このような理解しづらいスクリプトは嫌われているため、FirebaseではPromiseオブジェクトが採用されているのではないかと考えています。

2.thenメソッド

thenメソッドは、Promiseが正常終了した時に使われるresolve関数から引き継がれるメソッドです。メソッドの中で使われる引数は、成功コールバック関数と言われます。

3.catchメソッド

catchメソッドは、Promiseがエラー終了した時に使われるreject関数から引き継がれるメソッドです。メソッドの中で使われる引数は、失敗コールバック関数と言われます。

resolve関数とreject関数の定義

var db = new Promise(function(resolve, reject) {
        setTimeout(function() {
            (処理内容)
            if (true) {
                resolve();
            } else {
                reject();
            }
            
        }, 1000);
    });

お手本のコードを見る限り、resolveとrejectは関数のようには見えません。ですがMDNの公式ドキュメント(新しいタブで開く)と合わせて解釈すると、firebase-app.jsかfirebase-firestore.jsのどちらかで上記のスクリプトのような定義がされていると考えられます。