見出し画像

【Nuxt.js】非同期通信awaitのネストやチェーンについて

🎈 WPでも公開中です
https://wp.me/pc9NHC-1nm

#vue #nuxt #プログラミング #エンジニア

前置き

今回はasync/awaitで
Promiseの役割をする
awaitについてです💫

2つのパターンについて書いていきます。
・awaitでawaitをネスト
・awaitで.thenのメソッドチェーン

そもそも今までの記事では
const res = axios.get
みたいな取得した値を定数にして
その後で取得した値が返ってきた時の
処理を書いていました。
なのでそれ以外の使い方、
定数を使わなくても良い書き方が
すごく変に感じていたのです。。。

例えばfirebaseAuthで
アカウントを作成した後に
dispatchしたい場合
こんな感じのコードになります👇

export const actions = {
 async register({ dispatch }, payload) {
   try {
     await this.$fire.auth.createUserWithEmailAndPassword(
       payload.email,
       payload.password
     )
     dispatch('checkLogin')
   } catch (error) {
     console.log(error) //eslint-disable-line
   }
 },
}

これをもし
const res = await
にしてしまうとそれ以降
resを使用する必要がないため、
どうすれば良いのか
分からなかったのです🤔💭

ただこの2つのパターンを理解すれば
簡単ということが分かりました❣️☝️
ということでLet's Go❗️

⬇️Promise
 async/await
 簡単な使い方などは
 こちらをご覧ください🍀

参考:
ES2017でawaitのネストを避ける
【Nuxt.jsで近くのお店を探すアプリを作成】#4 async/await


awaitはPromiseで処理を止めるもの

ではまず
awaitがそもそも何か❓

ようは処理を止めるものです💥✋
awaitの処理が終わるまでに
止めておきたい処理を
中に書けば良いということです✍️

awaitの処理が終わるまで、
他の処理を停止させる
といった方が良いかもしれません。

.thenの場合は
「それが成功したら」の意味合いなので
日本語に置き換えた文法的に
しっくりきていました。
なので、
止めたい処理を書く
ということが最初は
中々理解できませんでした。。。
簡単に理解したいから
日本語に置き換える…
これはやめた方が良いですね。


##コード例①

⬇️簡単なコードはこちら
 前置きと同じコードです。

awaitが終わってからの処理を
その下に書いていきます。
この場合はfirebaseAuthの
アカウント作成が完了してから
dispatch('checkLogin')

export const actions = {
 async register({ dispatch }, payload) {
   try {
     await this.$fire.auth.createUserWithEmailAndPassword(
       payload.email,
       payload.password
     )
     dispatch('checkLogin')
   } catch (error) {
     console.log(error) //eslint-disable-line
   }
 },
}

##コード例②

awaitの後ろの.thenが省けます。

before

export const actions = {
 async login({ dispatch }, payload) {
   try {
     await this.$fire.auth
       .signInWithEmailAndPassword(payload.email, payload.password)
       .then(() => {
         dispatch('checkLogin')
         this.$router.push('/')
       })
       .catch()
   } catch (error) {
     console.log(error) //eslint-disable-line
   }
 },

after

export const actions = {
 async login({ dispatch }, payload) {
   try {
     await this.$fire.auth.signInWithEmailAndPassword(
       payload.email,
       payload.password
     )
     dispatch('checkLogin')
     this.$router.push('/')
   } catch (error) {
     console.log(error) //eslint-disable-line
   }
 },

##awaitのネストか.thenが必要な時とは

では今回の2つのパターンに
当てはまるコードは
どんな場合だと思いますか❓

こちらのコードを見てください👀
firebaseのStorageに
putが成功してから
getDownloadURLしたい(★部分)
このまま書いてしまうと、
オブジェクトがないというエラーです💥

これはStorageの公式コードにも
.thenが使われています。
Download Data via URL

Promiseの使用が必要です。
つまり今回の2つのパターンに当てはまります。

export const actions = {
 async register({ dispatch, state }, payload) {
   try {
     await this.$fire.auth.createUserWithEmailAndPassword(
       payload.email,
       payload.password
     )
     dispatch('checkLogin')
     const storageRef = this.$fire.storage.ref()
     ★storageRef.child(`users/${state.user.uid}.png`).put(payload.thumbnail)
     ★storageRef.child(`users/${state.user.uid}.png`).getDownloadURL()

   } catch (error) {
     console.log(error) //eslint-disable-line
   }
 },
}


Aの処理をしてからBの処理をしたい

ではawait内で、
更にawaitしたい場合はどうなるのか。
BでAの値を取得してから処理をしたい❗️
Aの処理を先にしてからBの処理をしたい❗️
って場合ですね🍀

おさらいですが、
この2つのパターンを使用します。
・awaitでawaitをネスト
・awaitで.thenのメソッドチェーン

awaitは.thenの代わりなので、
個人的にはせっかくなら
awaitで揃えた方が良いなぁ🎈🧸
と思いますが、
awaitのネストが嫌😖💦
という方もいるので、
お好み&チームに合わせて
どちらもできるとGood⭕️
まぁawaitに限らずですが。

##awaitのネスト

単純にawaitのネストをすればOK。
関数を分ける場合に有効。
async A() { await hogehoge }
async B() { await (await A()) hogehoge }

firebase関連でできるコードサンプル
探し中です🔍

##.thenでメソッドチェーン

awaitの処理が終わってから
やりたい処理を.then以降に記載✍️

async A() { await hogehoge.then(() => { hogehoge })}

###処理によってはawaitのネスト不可

目次「awaitはPromiseで処理を止めるもの」内
「awaitのネストか.thenが必要な時とは」
で出したAuthとStorageを
使用したコードが良い例です💡

registerしてupdateProfileしたい場合
await dispatchをしてもうまくいきません。
updateでurlが見当たらなくなってしまいます。
error 'url' is not defined

export const actions = {
 async register({ dispatch, state }, payload) {
   try {
     const res = await this.$fire.auth.createUserWithEmailAndPassword(
       payload.email,
       payload.password
     )
     dispatch('checkLogin')
     const storageRef = this.$fire.storage.ref()
     storageRef.child(`users/${state.user.uid}.png`).put(payload.thumbnail)
     await dispatch('update', payload)
     return res
   } catch (error) {
     console.log(error) //eslint-disable-line
   }
 },
 async update(payload) {
   const storageRef = this.$fire.storage.ref()
   await storageRef.child(`users/${state.user.uid}.png`).getDownloadURL()
   this.$fire.auth.currentUser.updateProfile({
     displayName: payload.name,
     photoURL: url,
   })
   this.$router.push('/register/finish')
   return url
 },
}

updateをregister内でしか
使わない前提の場合は
分ける必要がないのですが。
そして公式コード的にも
.thenが良さそうです。
Download Data via URL

なのでこの場合は
awaitの後に.thenで繋げる
メソッドチェーンを使用🍒
正しいコードはこちら👇

export const actions = {
 async register({ dispatch, state }, payload) {
   try {
     await this.$fire.auth.createUserWithEmailAndPassword(
       payload.email,
       payload.password
     )
     dispatch('checkLogin')
     const storageRef = this.$fire.storage.ref()
     storageRef
       .child(`users/${state.user.uid}.png`)
       .put(payload.thumbnail)
       .then(() => {
         storageRef
           .child(`users/${state.user.uid}.png`)
           .getDownloadURL()
           .then((url) => {
             this.$fire.auth.currentUser.updateProfile({
               displayName: payload.name,
               photoURL: url,
             })
             this.$router.push('/register/finish')
           })
       })
   } catch (error) {
     console.log(error) //eslint-disable-line
   }
 },
}


まとめ

awaitのモヤモヤが
スッキリしました✨
awaitのネストを使用したいのですが、
firebaseで試せるものが
まだ見当たらないため、
発見次第のせていきます🔍

🎈 WPでも公開中です
https://wp.me/pc9NHC-1nm

この記事が気に入ったらサポートをしてみませんか?