Preparing user context prior to executing controllers within AngularJS

I recently created an AngularJS application and integrated a REST API to fetch resources for the app. As part of the authentication process, I store the user's access token in a cookie. When the user reloads the page, I need to retrieve user information from the token using the following code snippet:

mymodule.run(function ($rootScope, $cookies, AuthService, Restangular) {
    if ($cookies.usertoken) {
        // call GET api/account/
        Restangular.one('account', '').get().then( function(user) {
            AuthService.setCurrentUser(user);
        });
    }
});

The AuthService module looks like this:

mymodule.factory('AuthService', function($http, $rootScope) {
    var currentUser = null;

    return {
        setCurrentUser: function(user) {
            currentUser = user;
        },
        getCurrentUser: function() {
            return currentUser;
        }
    };
});

However, when a controller that requires the user variable is accessed:

mymodule.controller('DashboardCtrl', function (AuthService) {
     var user = AuthService.getCurrentUser();
});

The issue arises because the controller code gets executed before the API call completes, resulting in a null value for the user variable. Is there a recommended approach to ensure that the controllers wait for user data to load before initiating?

I came across this link, but I am interested in a more overarching method to initialize the application context.

Answer №1

One method I find useful for handling this scenario involves storing the promise returned by Restangular in a centralized location, such as on an object like `AuthService`, which can then be accessed later within the controller. To begin, you can add a property to `AuthService` to store the new promise:

return {
    authPromise: {},  // this will keep track of the Restangular promise
    // setCurrentUser, getCurrentUser
    // ...

When making the call to Restangular, save the promise and make sure to return the user data so that it can be retrieved later in the controller. Here's an example:

AuthService.authPromise = Restangular.one('account', '').get()
                          .then( function(user) {
                              AuthService.setCurrentUser(user);
                              return user; // <--important
                           });

Finally, set up a new promise in the controller that will assign the `user` variable once resolved:

mymodule.controller('DashboardCtrl', function (AuthService) {
    var user;
    AuthService.authPromise.then(function(resultUser){
        user = resultUser;
        alert(user);
        // perform actions with user
    });
});

Demonstration: You can check out a JSFiddle demo where I've simulated an AJAX request using `$timeout`. The promise resolves when the timeout is completed.

Answer №2

One potential approach is to centralize the authentication process within a parent controller. This can be implemented by calling the Authenticate() method on the parent controller in the resolve function of your routing configuration, like so:

resolve:DashboardCtrl.$parent.Authenticate()
.

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

Alert! Server node encountered an issue while handling the response: process.nextTick(function(){throw err;});

Currently, I am working on a simple application to familiarize myself with Mongo, Express, and Node. An issue arises when I attempt to utilize res.json(docs) in the success conditional during the GET request, generating an error process.nextTick(function( ...

Is there a way to add an entire array of child nodes to a parent node in a single operation using JavaScript?

Is there a quick way in JavaScript to attach an array of child nodes to a parent node all at once? I'm looking for a method that will avoid triggering unnecessary repaints. So far, I attempted using parent.appendChild(arrayOfNodes), but it resulted ...

Creating Tree diagrams with pie charts using D3

Has anyone tried creating a D3 pie component within each node of a tree? I've managed to build the tree and a single pie separately, but I'm struggling to combine them. My JSON data looks like this: window.json = { "health": [{ "value" ...

Next.js fails to refresh the content upon initial view

Snippet from my index.js file: import Post from "@/components/Post" import Modal from "@/components/Modal" import {useState} from "react" export default function Home() { // Setting up states const [modalTitle, setModalTitle] = useState('Title&a ...

Just built a React App including a blog functionality, but for some reason the blog posts are not showing up. Any suggestions on how to fix this issue

I'm currently working on a project that involves creating a blog page for our react app. Despite my efforts, I am facing difficulty in getting the blog posts to show up. In order to retrieve all the posts from my MYSQL database, I have set up an API ...

Transferring Data to EJS Template

I have been facing a challenge in passing a value from a POST route to an EJS file for display. Despite trying various methods like redirecting, sending, and rendering the results, the data won't make its way to the EJS file. Below is the POST route ...

Is it considered acceptable to modify classes in a stateless React component by adding or removing them?

My stateless component functions as an accordion. When the container div is clicked, I toggle a couple of CSS classes on some child components. Is it acceptable to directly change the classes in the DOM, or should I convert this stateless component to a ...

Change a space-separated string containing coordinates into an array of JavaScript objects

Here is a string separated by spaces: const coordinates = "42.44492,75.637764 42.445503,75.64534 42.433681,75.6604" Now, we want to convert it into an array of objects: const coordinatesArray = [ { lat: 42.44492, lng: 75.637764 }, { lat: 42.4455 ...

Exploring AngularJS: A guide to extracting data from an image file

When attempting to send the image data to the back-end, I encountered an error while trying to read the image file: Uncaught TypeError: Failed to execute 'readAsArrayBuffer' on 'FileReader': parameter 1 is not of type 'Blob'. ...

Step-by-step guide on invoking a recursive function asynchronously in JavaScript

As I delved into the realm of creating a unique Omegle clone using Node.js and Socket.io for educational purposes, I encountered a challenge that has left me scratching my head. The socket ID of clients along with their interests are stored in an array of ...

What could be causing my tabs (such as HOME, ABOUT ME..) not displaying the correct paragraph or section content?

I have set up navigation tabs on my website using anchor tags, but they are currently not linked to any specific paragraphs. I want the corresponding paragraph to be displayed when a tab is clicked, but I'm unsure how to add this functionality using j ...

Clicking randomly on the page to conduct test trials

Currently, I am seeking a way to ensure that my web page is flawless, specifically in terms of broken paths. Given that my website will utilize a touch screen interface, it is crucial to test the entire page thoroughly. While I have limited experience in a ...

Encountering the error message "ReferenceError: parsePayload cannot be accessed before initialization"

Check out this code snippet: Experiencing an issue with 'ReferenceError: Cannot access 'parsePayload' before initialization' Any assistance would be appreciated const express = require("express"); const { createToDo, updateToD ...

Pass a JSON object to PHP when AJAX call is successful

Within my Controller, there exists an array named $data. Here is the output of its var dump: array 'urls' => array 0 => array 'link_id' => string '1' (length=1) 'link_name ...

Create a custom definition for the useSelector function within a separate TypeScript file in a React

Question: Is it possible to define a type like <TRootState, string> in an external file and use it directly inside multiple Component files? External file: export type TUser = <TRootState, string> // This method does not work Component's ...

Tips for avoiding accidental unit conversion in jQuery

Imagine having the following code: var $element = $('<div/>'); $element.css("margin-left", "2cm"); console.log($element.css("margin-left")); When tested in Chrome, it doesn't return anything, but Firefox shows "75.5833px". Any sugges ...

Avoiding repetition in json array using reactjs with the help of axios

After receiving guidance from @Akrion, I managed to resolve the issue! Check out my comments below our conversation for the solution. I am relatively new to reactJS and axios, but I recently collaborated with a classmate on a project. Now, I find myself s ...

Troubleshooting: Issues with jQuery.on method functionality

I'm currently using jQuery version 1.9.1 and I have a situation where I need to perform an action on a dynamically added td element. I attempted to utilize the jQuery.on function, however my code is not being triggered. Can someone please provide some ...

Step-by-step guide on how to index timestamp type using Knex.js

I'm in the process of indexing the created_at and updated_at columns using knex js. However, when I try to use the index() function, I encounter the following error: Property 'index' does not exist on type 'void' await knex.sche ...

Is it possible to apply a filter within ng-repeat to search for multiple items based on a particular field?

Currently, I am in the process of developing a filtering solution for a grid that involves multiple checkboxes in a panel. My current approach utilizes the filter integrated into the ng-repeat directive. However, I am facing a challenge in making it filter ...