Search code examples
javascriptvue.jspromiseasync-awaitvuex

Why async function continues after await (in vuex)


From one vuex action (togglePostLike) I'm trying to await another vuex action (requiresAuth) using async/await.

I had expected that if return Promise.resolve() was never called then the first action should get stopped at await dispatch (and get garbage collected), but it proceeds to the console.log('this is called SECOND') even without the resolve.

Shouldn't await stop the execution without resolve? How can I get that intended behavior?

/store/modules/post.js

async togglePostLike ({ dispatch, rootState }, post) {
    await dispatch('user/requiresAuth', null, { root: true })
    console.log('this is called SECOND, but why without resolve')
    // I don't want this stuff to execute without the resolve
    if (post.likes.includes(rootState.user._id)) {
      dispatch('addPostUnlike', post)
    } else {
      dispatch('addPostLike', post)
    }
},

/store/modules/user.js

async requiresAuth ({ state }) {
      if (!state.authenticated) {
         router.push({ name: 'login', query: { comeBack: true } })
         $(`.modal`).modal('hide')
         console.log('this is called first')
       } else {
         console.log('this is NOT called')
         return Promise.resolve()
       }
  },

EDIT: how it looks without async/await

As I understand from the vuex docs, dispatch returns a promise anyway. Using the following:

post.js

if (dispatch('user/requiresAuth', null, { root: true })) {
     // still executes before return false   
}

user.js

requiresAuth ({ state }) {
  if (!state.authenticated) {
     // do stuff (does it)
     return false
   }
   return true
}

Solution

  • An async function like requiresAuth always returns a promise that is resolved with the return value (including undefined if no return statement is evaluated). It does not make a difference whether the function ends without a return, with a return;, with a return undefined;, with a return Promise.resolve() or with a return Promise.resolve(undefined) - they are indistinguishable from the outside.

    Either return a boolean and then branch on it, or just throw an exception.