VueX getter not functioning with Async/Await, while log function does work

I am working on a situation where I have a collection of conversations associated with userIDs that I need to iterate through. Within this loop, I must make a call to Firebase to retrieve the corresponding userNames and then generate an object containing the conversations, userNames, and userIDs.

Despite using async/await, when I log the result in the console it appears correct. However, for some reason, the return statement directly after logging is resulting in undefined. Even though they are essentially the same object, why is this occurring?

Snippet from store.js Getter

getConvosObj: state => {
  var convoObj = {};
  var userConvos = state.userProfile.convos;
  async function asyncFunction() {
    for (const key in userConvos) {
      if (userConvos.hasOwnProperty(key)) {
        const userID = userConvos[key];
        var userName;
        await fire.database().ref('/users/' + userID + '/userName').once('value', async (snapshot) => {
          userName = await snapshot.val();
          convoObj[key] = {userName, userID}
        })
      }
    }
    console.log(convoObj);   //result: correct object
    return convoObj;         //result: undefined
  }
  asyncFunction();
}

Answer №1

Why is this happening ?

The reason for this issue is because you have invoked an asynchronous function synchronously.
Let's simplify your code.

getConvosObj: state => {
    async function asyncFunction() {
        // ...
    }

    asyncFunction();
}

At this point, your getConvosObj() will not return anything as it completes before asyncFunction().
You need to wait for asyncFunction() to finish for the following code to work:

getConvosObj: async state => { // <- changed here
  async function asyncFunction() {
    // ...
  }

  await asyncFunction(); // <- changed here too
}

However, this approach is not recommended as getters are not designed to be asynchronous.
While it may work, try exploring a different solution.

So what should you do ?

Utilize actions before using getters

Here's a fundamental solution.

Async functions should be placed in actions.
Therefore, structure your store like this:

export default () => 
  new Vuex.Store({
    state: {
      convoObj: null
    },
    mutations: {
      updateConvoObj(state, payload) {
        state.convoObj = payload;
      }
    },
    actions: {
      async fetchAndUpdateConvoObj({ state, commit }) {
        const fetchUserData = async userId => {
          const snapShot = await fire.database().ref('/users/' + userID + '/userName').once('value');
          const userName = snapShot.val();

          return {
            userName: userName,
            userID: userId
          }
        }

        const userConvos = state.userProfile.convos;

        let convoObj = {};
        for (const key in userConvos) {
          if (userConvos.hasOwnProperty(key)) {
            const userId = userConvos[key];
            const result = await fetchUserData(userId);

            convoObj[key] = {
              userName: result.userName,
              userId: result.userId
            }
          }
        }

        commit('updateConvoObj', convoObj);
      }
    }
  });

Then, call your actions before utilizing getters in your sample.vue:

await this.$store.dispatch('fetchAndUpdateConvoObj');
convoObj = this.$store.getters('getConvoObj');

Wait for the database to update and the store to refresh before retrieving its state.
Making sense now?

Use vuexfire to link your store directly to the Realtime Database

Another option is to employ vuexfire which keeps the store's state synced with the realtime database, enabling you to access getters without calling actions.
If interested, look up some examples of using that plugin :)

I've made substantial changes to the original code, so there might be some errors or typos.
Kindly review and correct them if found.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating cookies in R Shiny: Storing variables for future use

Writing a fixed string to cookies can be done easily using methods like Cookies.set(\'cookie_2\', \'value\', { expires: 7 }) (see tutorial here). However, saving the variable user to cookie_2 may require a different ...

Grab the SVG and resize it to a smaller scale

I have a small application built using Raphael.js that creates a node network with SVG and reorganizes it based on user selections. My goal is to capture the SVG image I've created and display it in a "mini-map" format at the bottom of the screen. Si ...

Accessing the ID of individually selected rows as well as multiple rows in Vuetify data tables by utilizing the "show select" property

In order to delete specific records from the tables based on user selection, there needs to be functionality implemented where if a user selects any 3 options, a delete button will appear. This delete button should allow for the deletion of those specifi ...

Tips for eliminating empty trailing values and Carriage Returns from a JavaScript array

I needed a way to eliminate empty elements and Carriage Returns from the end of an array. Here's an example of what my array looks like: Input arr: ['', 'Apple', '', 'Banana', '', 'Guava', & ...

What is the best way to incorporate this CodePen snippet into a Vue project?

Can anyone help me figure out how to incorporate this awesome animation from CodePen (link here: https://codepen.io/iprodev/pen/azpWBr) into a Vue project? I've tried implementing it like so: <template> <div> <canvas heigh ...

Error occurs when using Express.js in combination with linting

https://www.youtube.com/watch?v=Fa4cRMaTDUI I am currently following a tutorial and attempting to replicate everything the author is doing. At 19:00 into the video, he sets up a project using vue.js and express.js. He begins by creating a folder named &apo ...

The React JSON Unhandled Rejection problem requires immediate attention

While working on a form in React 16, I reached out to a tutor for some guidance. However, when trying to mock the componentDidMount, I encountered an error that has left me puzzled. The app still runs fine, but I am curious as to why this error is occurrin ...

Can you tell me how to add a variable to an array of objects in JavaScript?

I am currently engaged in a small project aimed at: Reading data from a CSV file (such as employee names and shifts) Displaying this data on FullCalendar. How can I incorporate the CSV result into this line of code: { id: 'a', title: 'Audi ...

Is it possible to combine jQuery Mobile with Vue.js in a project?

Exploring new web technologies can be quite challenging, especially when it comes to making them work on mobile devices. I found AngularJS particularly tricky in this regard. I'm considering trying Vue.js along with some jQuery mobile elements instead ...

Having trouble retrieving data from MongoDB and rendering it on an HTML page

Creating a Model Named Field.js in Mongoose const mongoose = require('mongoose'); mongoose.connect('mongodb://localhost:27017/SuperchainV1', { useNewUrlParser: true }); mongoose.set('useNewUrlParser', true); ...

The JQuery File-Upload plugin remains inactive even after a file has been chosen

I am currently working on integrating the JQuery File-Upload plugin (). The issue I'm facing is that it doesn't respond when a file is selected. Here are some potential problems to consider: No errors appear in the Chrome console. Selecting a ...

The Vue.js scripts and styles declared in the index.html file seem to be malfunctioning

I acquired a theme that includes html, css3, and js files, and I included the file path as shown below: <!-- Basic --> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Porto - Responsive HTML5 Te ...

What is the best way to position the button under the label?

I attempted to place the 'search' button underneath the 'branch' label, below is the code snippet I used <template> <base-header class="pb-4 pb-5 pt-6 pt-md-6 bg-gradient-success"> <template> <div> ...

Vue does not recognize the Nuxt $route

Greetings, I've encountered a strange issue. I'm working on a Nuxt app with Typescript. In the created hook, I am using console.log to log this.$route. The log is functioning correctly and I am able to read the params from the route. However, d ...

The value entered is displaying as not defined

As a newcomer to the world of javascript, I am diving into creating a simple To Do list. The basic functionality is there, but I'm scratching my head trying to figure out why the input value in my code keeps returning undefined. The remove button is ...

Preventing page navigation in JavaScript: Why it's so challenging

I am encountering an issue with a link element that I have bound a click event to (specifically, all links of a certain class). Below is an example of the link element in question: <a id="2" class="paginationclick" style="cursor: pointer;" href=""> ...

Generate a configuration file that allows for the reading and storage of modifications

Is there a way to create a configuration file (JSON) on the local file system using JavaScript where I can write and modify data without losing it when the application is restarted? Any suggestions or solutions for this problem? Thank you for your assista ...

Guide to making a Typescript interface by combining elements from two separate interfaces without utilizing inheritance

Programming Language: Typescript I am looking to combine the properties of two interfaces as the value of an indexable-type within a third interface. Interface 1: export interface Employee { id: string name: string } Interface 2: export interfa ...

Issue with RegisterClientScriptCode function following a partial postback

In a SharePoint website, the code below is contained within a user control: ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "jquery144", "<script type=\"text/javascript\" src=\"/_layouts/Unicre.Web.RUOnline.Controlos/Script ...

Difficulty in constructing an array from several Firebase Storage URLs

I'm attempting to retrieve multiple image URLs and store them in an array using Firebase Storage. However, I am facing issues accessing specific index positions within the testArray: var testArray = [] listAll(ref).then((res) => { res.item ...