Search code examples
javascriptvue.jsasync-awaitpromisevuex

Having issues with Await not waiting using async/await


I have a vue.js project and am using Vuex for my store. I am trying to process all notifications to users within the store and I am having some issues with async/await.

I am sure its something very simple and trivial but I am stuck. Any help is much appreciated.

Here is my function

async getNotifications() {
    
    console.log('1')

    const internalNotifications = await this.$store.getters['AppData/getInternalNotifications']

    console.log('2')

    if(internalNotifications) {

        this.notifications = internalNotifications
        this.message = true

        console.log('4 ', internalNotifications)
    }
}

Here is my function in the store to get the notifications and dispatch them.

async getInternalNotifications({ dispatch }, { cid, user, roles, isSupperAdmin }) {

    console.log('getInternalNotifications')

    let internalNotifications = []
    
    // Get all the notifications for this church
    let getAllNotifications = await db
        .collection('notifications')
        .where('cid', '==', cid)
        .where('active', '==', true)
        .orderBy('created')
        .get()

    for (const notificationDoc of getAllNotifications.docs) {
        let notification = notificationDoc.data()
        notification.id = notificationDoc.id

        // check to make sure this notification has not already been read
        let getAllReadNotifications = await db
            .collection('notificationsread')
            .where('notificationid', '==', notification.id)
            .where('userid', '==', user.uid)
            .get()

        if (getAllReadNotifications.empty)
            internalNotifications.push(notification)

    }
    
    if (!isSupperAdmin && internalNotifications.length > 0) {

        const hasAudience = internalNotifications.filter((el) => {
            return roles.some(r => el.audience.includes(r))
        })

        hasAudience.sort((a, b) => (a.created < b.created) ? 1 : -1)

        internalNotifications = hasAudience[0]

    }

    console.log('3 ', internalNotifications)

    dispatch('addInternalNotification', internalNotifications)

},

My thinking is when viewing the console log I should see the logs in order 1,3,2,4 but instead I get 1,2,4,3 and as you can see from the screen shot it's an Observer not the actual array/object.

see screen shot of console log enter image description here


Solution

  • What appears to be happening, and looking at the order of logs, is that this.$store.getters does not return a Promise and therefore adding await does nothing.

    Make sure that this.$store.getters is actually returning a Promise that can be awaited or look at using Actions. From the docs if you wanted to use an action for this, you could try something like the following:

    NOTE All of this is untested and I don't know vue, so use with caution knowing changes may be needed and best practices may not be getting followed by this approach.

    actions: {
      async getInternalNotifications({ dispatch }) {
        return new Promise((resolve, reject) => {
          console.log('getInternalNotifications')
          let internalNotifications = []
    
          // Get all the notifications for this church
          let getAllNotifications = await db
            .collection('notifications')
            .where('cid', '==', cid)
            .where('active', '==', true)
            .orderBy('created')
            .get()
          for (const notificationDoc of getAllNotifications.docs) {
            let notification = notificationDoc.data()
            notification.id = notificationDoc.id
    
            // check to make sure this notification has not already been read
            let getAllReadNotifications = await db
                .collection('notificationsread')
                .where('notificationid', '==', notification.id)
                .where('userid', '==', user.uid)
                .get()
    
            if (getAllReadNotifications.empty)
                internalNotifications.push(notification)
          }
        
          if (!isSupperAdmin && internalNotifications.length > 0) {
            const hasAudience = internalNotifications.filter((el) => {
              return roles.some(r => el.audience.includes(r))
            })
            hasAudience.sort((a, b) => (a.created < b.created) ? 1 : -1)
            internalNotifications = hasAudience[0]
          }  
          console.log('3 ', internalNotifications)
          dispatch('addInternalNotification', internalNotifications)
          resolve(internalNotifications)
    
          // TODO: Reject error scenarios, e.g. wrap you db calls in a try...catch and reject the promise with the error
        })
    }
    
    async getNotifications() {
        
        console.log('1')
    
        const internalNotifications = await this.$store.dispatch('AppData/getInternalNotifications')
    
        console.log('2')
    
        if(internalNotifications) {
    
            this.notifications = internalNotifications
            this.message = true
    
            console.log('4 ', internalNotifications)
        }
    }