Ensure that the vue-router guard waits for the completion of the axios API call in Vuex before proceeding

I am currently working with a django-rest-axios-vuejs application stack, and I have a specific task that involves the vue-router.

Within the beforeEach guard of the vue-router, I am checking permissions by verifying something in the me object within the vuex store. While everything functions correctly, there is an issue when the page is refreshed.

Upon refreshing the page, the vuex store gets cleared, causing my beforeEach function to attempt checking the now empty me object in the store.

My goal is to retrieve the me object from the API if it is not present in the store. However, due to the asynchronous nature of fetching data, the hasPermission() method executes before the API call is completed.

I attempted using the await keyword before the API call, but it did not yield the desired result.

This is my beforeEach guard :

router.beforeEach(async (to, from, next) => {
  const isLoggedIn = getIsLoggedIn()
  handleLoggedInStatus(isLoggedIn)
  if (to.meta.requiresAuth) {
    if (isLoggedIn) {
      if (to.meta.permission) {
        if (!store.state.me) await store.dispatch('FETCH_ME')
        hasPermission(to.meta.permission) ? next() : next({ name: 'HomePage' })
      } else {
        next()
      }
    } else {
      next({ name: 'LoginForm' })
    }
  } else {
    next()
  }
})

This is my action from the store :

actions: {
    FETCH_ME: (state) => {
      http
        .get('base/users/me/')
        .then(response => {
          state.me = response.data
        })
        .catch(error => {
          console.log(error)
        })
    }
  }

To overcome the timing issue, I found a workaround:

function sleep (ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}

router.beforeEach(async (to, from, next) => {
  const isLoggedIn = getIsLoggedIn()
  handleLoggedInStatus(isLoggedIn)
  if (to.meta.requiresAuth) {
    if (isLoggedIn) {
      if (to.meta.permission) {
        if (!store.state.me) {
          store.dispatch('FETCH_ME')
          await sleep(2000)
        }
        hasPermission(to.meta.permission) ? next() : next({ name: 'HomePage' })
      } else {
        next()
      }
    } else {
      next({ name: 'LoginForm' })
    }
  } else {
    next()
  }
})

In this setup, we introduce a brief delay of "random" (2 seconds) using a small sleep() method.

As someone who is relatively new to using async and await, I wonder what I might be missing to make await store.dispatch('FETCH_ME') function properly?

Any guidance on this matter would be greatly appreciated. Thank you in advance :)

Answer №1

I have a personal project with a similar approach. I am not relying on meta tags.

async beforeEnter(to, from, next) {
   await store.dispatch('getUser')
   if (store.getters.user) return next()
   next('/login')
}

The concept behind this logic is as follows: If the user is authenticated, there will be a cookie stored in the browser that is sent along with the store dispatch. When the backend verifies the token's validity and returns the user data, the getter retrieves the user, confirming their logged-in status. I believe your implementation should align with this principle.

Answer №2

After much searching, I stumbled upon this RESOURCE that had eluded me until now...

This discovery led me to revamp my FETCH_ME action as follows :

FETCH_ME ({ commit }) {
  return new Promise((resolve, reject) => {
    http
     .get('base/users/me/')
     .then(response => {
       commit('SET_ME', response.data)
       resolve()
     })
     .catch(error => {
       console.log(error)
       reject(error)
     })
   })
}

where SET_ME is a mutation that was already in place :

SET_ME: (state, user) => {
  state.me = user
},

This setup has proven effective for my scenario, particularly when used within the router.beforeEach guard :

if (!store.state.me) await store.dispatch('FETCH_ME')
effectively waits for the dispatch action to complete.

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

What steps can you take to ensure your PhoneGap app on Android doesn't freeze while making asynchronous AJAX calls?

Having an issue with my PhoneGap-Android app that uses Jquery. When making an ASYNCHRONOUS AJAX call, the app freezes and waits for the call to finish, especially noticeable on a GSM connection. I would expect this behavior if I were using synchronous req ...

"Troubleshooting: Why is TailwindCSS not functioning correctly in my NextJS

My project utilizes a combination of NextJS, TailwindCSS, and Typescript. Strangely, everything displays correctly in the development environment, but once in production, the tailwindcss classes are not being applied. For reference, here is the link to t ...

"Using Jest to specifically test the functionality of returning strings within an object

Attempting to run a jest test, it seemed like the issue was with the expect, toBe section as I believed that the two objects being compared (data, geonames) were exactly the same. However, upon closer inspection, they turned out to be different. The struct ...

Switch up the color of checkboxes with a dropdown menu option

I have an HTML dropdown code and I am trying to trigger a click event when a specific value is selected. Once this value is clicked, I want some checkboxes to change color. <select> <option value="calculate">calculate</option> ...

Encountering issues with the routing in my live Node.js project: ERROR

I am encountering issues with my project in production. I suspect it could be due to a misconfiguration or something similar. Could you please review the provided code snippets and see if you notice any potential issues? The project works fine locally, bu ...

Generating HTML table rows dynamically in Angular based on the number of items stored in a $scope variable

In my current project, I am utilizing Angular to dynamically populate data in an HTML table. Instead of manually coding each row for display, I am in need of a solution that allows me to programmatically define each HTML row. The Angular controller snippet ...

Challenges with loading content and async JavaScript within websites

I decided to replace the content on index.htm with the content from project.htm. By clicking on a#front, it redirects to project.htm and dynamically updates the content. However, I am facing an issue regarding how to run the javascript that accompanies thi ...

Having trouble triggering the button with querySelector in Angular

I have a dynamic page where I need to click on a button. I tried the code below, but it is not working and not showing any alert. However, if we use the same code in the browser console, it executes and shows an alert. Can someone please suggest how to r ...

"Clicking on a handler will replace the existing value when the same handler is used for multiple elements in

import React, { useState, useEffect } from "react"; const Swatches = (props) => { const options = props.options; const label = Object.keys(options); const values = Object.values(options); const colors = props.colors; const sizes = p ...

Changing the color of placeholder text in MUI 5 TextField

Looking to customize the text color and placeholder text color in my MUI TextField component to be green https://i.sstatic.net/NZmsi.png The documentation doesn't provide clear instructions, so I attempted a solution that didn't work: <TextF ...

The parent's height dynamically adjusts based on the height of its visible children using only CSS

I am dealing with the following structure: <div class="body"> <div class="wrapper"> <div class="dialog"> <div class="content-0"></div> <div class="content-1&quo ...

Translating Encryption from Javascript to Ruby

I have an application which utilizes HTML5 caching to enable offline functionality. When the app is offline, information is stored using JavaScript in localStorage and then transmitted to the server once online connectivity is restored. I am interested in ...

Displaying the Selected Value from the DropDown in the Menu

I am working with Bootstrap5 and have the following dropdown menu in my code. Instead of displaying "Year," I would like to show which member was selected. How can I achieve this? <div class="dropdown"> <button class="btn btn- ...

jQuery selector for attributes with values that are higher than a specific amount using the ">" symbol or lower than a certain value using the "<" symbol

I currently have several div elements with the following structure: <div class="roomnamecta" data-price="1189" data-adult="3">Room 1</div> <div class="roomnamecta" data-price="578" data-adult ...

I'm facing an issue where the data I retrieved is not displaying properly in my template within nuxt 3

After fetching data from an api, I can see it logged in my async function. However, the data stored in my array is not rendering on my template in Nuxt 3 The script setup includes: //ARRAY OF ALL THE DAILY WEATHER DATA PER DAY let allDataWeather=[]; ( ...

Move and place multimedia items using IE's drag and drop feature

Is there a way to enable the drag and drop feature across different browsers or windows using HTML5's native DnD API? I have noticed that when I set the data type to 'text' in Internet Explorer, it functions properly. However, if I attempt t ...

What is the reason for Backbone including model details within {model: {model_property: value,...}} when saving a model?

I am currently developing an application using node.js and backbone.js. However, I have encountered an issue where saving a model results in the JSON being nested inside a model dictionary. node = new NodeModel({prop1:"value1", prop2:"value2"}); node.save ...

Error: The function cannot be called because it is undefined

As a newcomer to JavaScript, I recently copied a script from jqueryui.com for the dialog widget and pasted it into my Yii project. However, upon testing the code, I encountered an error: Uncaught TypeError: undefined is not a function associated with the ...

Encountered an issue with md-autocomplete: Attempting to read property 'success' of an undefined element

I encountered an issue while using Material Angular framework and md-autocomplete. The error message I receive is: Cannot read property 'success' of undefined. Below is the snippet of my code: /*My app.js*/ var app = angular.module('app&apo ...