Home > Enterprise >  Having issues with Await not waiting using async/await
Having issues with Await not waiting using async/await

Time:11-09

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

CodePudding user response:

I was working on a web app recently and I think I can help. Someone correct me if I'm wrong, but typically after calling an async function, I follow it with a .then. Example:

const myPromise = anAsyncFunction() // should return a promise

myPromise.then (
    function(value) {
        // function to be executed when the async function is finished
    },
    function(error) {
        // error handling
    }
)

Otherwise, my app would not wait for the async function to finish and would not have the right variable in time to process it.

CodePudding user response:

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)
    }
}

  • Related