【Vue × Firebase】非同期処理について



自身の備忘録として残します。

postItem()が押下されたら「この内容で投稿しますか？」とアラートを表示させてif文で以下のように分岐してます。

「OK」の場合･･･Firestoreのpostsというコレクションを参照して保存。その後、「投稿しました」というアラートを表示し、
　　　　　　　　投稿が画面上でも確認できるようにrouter.goを使ってリロード実行。　　
「キャンセル」の場合･･･何も実行せず「キャンセルしました」というアラートを表示。

if文の後は.catch()でエラーを吐き出しております。

#問題点

router.goを使わずに手動でリロードをしたら画面上に新しく追加した投稿が表示されるが、
router.goを使うとリロードは実行されるが、Firestoreにすら保存されず、画面表示もしない。

#修正前のコード

```javascript
   postItem() {
      const currentUser = firebase.auth().currentUser;
      this.uid = currentUser.uid;
      const id = firebase
        .firestore()
        .collection("posts")
        .doc().id;
      this.$swal({
        title: "内容確認",
        text: "この内容で投稿しますか？",
        icon: "info",
        buttons: true,
        dangerMode: true,
      })
        .then((willDelete) => {
          if (willDelete) {
            firebase
              .firestore()
              .collection("posts")
              .add({
                title: this.title,
                description: this.description,
                genre: this.genre,
                time: firebase.firestore.FieldValue.serverTimestamp(),
                //サーバ側で値設定
                id: id,
                //dataにデータを作ってないので、thisは付けなくてOK!
                uid: this.$route.params.uid,
              });
            this.$swal("投稿しました。", {
              icon: "success",
            });
            this.$router.go({ path: `/board/${this.uid}`, force: true });
          } else {
            this.$swal("キャンセルしました。");
          }
        })
        .catch(() => {
          this.$swal("投稿出来ませんでした。", {
            icon: "error",
          });
        });
    },
```

#原因
router.goが先に実行されてFiresutoreに保存がされていなかった為、
.then()内にアラートとrouter.goの処理をいれることで改善されました。



#修正後のコード

```javascript
 postItem() {
      const currentUser = firebase.auth().currentUser;
      this.uid = currentUser.uid;
      const id = firebase
        .firestore()
        .collection("posts")
        .doc().id;

      this.$swal({
        title: "内容確認",
        text: "この内容で投稿しますか？",
        icon: "info",
        buttons: true,
        dangerMode: true
      })
        .then(willDelete => {
          if (willDelete) {
            firebase
              .firestore()
              .collection("posts")
              .add({
                title: this.title,
                description: this.description,
                genre: this.genre,
                time: firebase.firestore.FieldValue.serverTimestamp(),
                id: id,
                uid: this.$route.params.uid
              })
              .then(() => {
                this.$swal("投稿しました。", {
                  icon: "success"
                });
               this.$router.go({ path: `/board/${this.uid}`, force: true });
              })
              .catch(() => {
                console.log("err");
              });
          } else {
            this.$swal("キャンセルしました。");
          }
        })
        .catch(() => {
          this.$swal("投稿出来ませんでした。", {
            icon: "error"
          });
        });
    },
```

#おまけ

以下の場合、コンソール内の「a」と「b」どちらが先に実行されるか。 


答えは、「b」

Firebaseは外部から通信しているので、通信に多少たりとも時間を要する。
非同期では、アラート等の表示は先にするが、通信が必要な部分は後回しで
例の場合、先に「b」が実行されてから「a」が実行される為

したがって、修正前では先にリロードが実行されFirestoreに保存されなかった。


```javascript
test() {
      this.$swal({
        title: "内容確認",
        text: "この内容で投稿しますか？",
        icon: "info",
        buttons: true,
        dangerMode: true
      })
        .then(() => {
          if () {
            firebase
              .firestore()
              .collection("test")
              .add({
               a:a
               b:b
               c:c
              })
              .then(() => {

               ///　console.log("a")

              });
              .catch(() => {});
          } else {
            this.$swal("キャンセルしました。");
          }
        })

        ///　console.log("b")

        .catch(() => {});
        });
    },
```