Angular interceptor automatically aborting API request

I have implemented a guard in my Angular application to validate user authorizations before granting access to a specific page. The guard makes an asynchronous API call to retrieve the necessary authorization information. While most of the time it works smoothly, I encountered a peculiar issue during performance testing on Chrome with Slow 3G throttling. The call made by the guard gets automatically canceled after approximately 445ms.

Below are the key sections of the code:

auth.service

import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Authorization } from '@models';
import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';

@Injectable()
export class AuthService {
    constructor(private http: HttpClient) {}

    getAuthorizations(id: number): Observable<Authorizations> {
        return this.http
            .get(`/api/authorizations`)
            .pipe(
                map(res => {
                    return !!res && (<any>res).data.authorizedActions
                        ? (<any>res).data.authorizedActions
                        : null;
                })
            );
    }
}

app.module

export const appRoutes: Routes = [
            {
                path: '',
                component: HomeComponent,
            },
            {
                path: 'budget',
                canActivate: [BudgetGuard],
                loadChildren: () => import('./budget').then(m => m.BudgetModule),
            },
];

budget.guard

import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot } from '@angular/router';
import { AuthorizedBusinessAction } from '@tproj/models';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { AuthService } from '../auth.service';
import { of } from 'rxjs';

@Injectable()
export class BudgetGuard implements CanActivate {
    constructor(private authService: AuthService, private router: Router) {}

    canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
        const userId = route.params.userId;
        return this.authService
            .getAuthorizations(userId)
            .pipe(map(auth => {
                if (auth.userIsAuthorized) {
                   return auth.userIsAuthorized;
                }
                this.router.navigate([`/`]);
            }));
    }
}

If anyone has any insights or suggestions, I would greatly appreciate it. Thank you!

Answer №1

It is recommended not to make the API call inside the guard. Instead, make the API call when the root app is loaded and save the user Object inside an observable. Then, inside BudgetGuard, you can subscribe to it.

Here is an example of how you can do this:

    constructor(private _authService: AuthService) {
        this._authService.currentUser.subscribe(u => {
            this.authorized = u != undefined ? true : false
        })
    }
    canActivate() {return this.authorized}

In the auth.service, you can implement a method like this:

getUser() { this.currentUser.next(user)}

You may also want to consider using Angular interceptors for handling API calls.

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

An error occurred while attempting to generate two requests on the API

My online store consumes an API, but I am having trouble with the requests that the site is making. Every time I make a request, I receive two: one with OPTIONS and another with POST. This causes the API to become jumbled up. Can anyone offer some assist ...

After updating the TypeScriptOutDir configuration, breakpoints are not being reached

Currently, I am utilizing Visual Studio Professional 2013 Update 3 and have developed a Node console Application with the simple "hello world" log instruction. Setting a breakpoint in this instruction and running the debugger functions smoothly, hitting th ...

Steps for resetting the ng-multiselect-dropdown

Is it necessary to wrap the ng-multiselect-dropdown in a form in order to reset it? code - app.component.html <div> <p id = "node">Select a Root API Object - </p> <p style="width:50%"> <ng-multiselect-dropdown [placeho ...

How can you implement a null filter in the mergeMap function below?

I created a subscription service to fetch a value, which was then used to call another API. However, the initial subscription API has now changed and the value can potentially be null. How should I handle this situation? My code is generating a compile e ...

Unable to retrieve user data during route navigation

In my Angular application, I have created a service called AuthService: export class AuthService { public currentUser: Subject<firebase.User> = new Subject(); public currentUserId: Subject<string> = new Subject(); constructor(pri ...

What is the best way to dynamically translate TypeScript components using transloco when the language is switched?

I am seeking clarification on how to utilize the TranslocoService in TypeScript. Imagine I have two lang JSON files for Spanish and Portuguese named es.json and pt.json. Now, suppose I have a component that displays different labels as shown in the followi ...

Angular 2 integration for Oauth 2 popup authorization

I am in the process of updating an existing Angular application to utilize Angular 2. One challenge I am facing is opening an OAuth flow in a new pop-up window and then using window.postMessage to send a signal back to the Angular 2 app once the OAuth proc ...

Strange behavior observed in Angular Reactive form

I've been troubleshooting this code snippet: login.component.html <div class="main"> <div class="image"> <img src="./assets/icons/login.png" alt="Login"> <p>Sign in t ...

I have saved a text file on my device and now I am looking to showcase its contents on an HTML webpage using JavaScript, rather than downloading

I have been working on converting a PDF document into a base64 string. After successfully converting it and saving it to a text file, I am currently able to download the text file. However, I do not want users to have to download the file, but rather dis ...

What is the process of hosting an Angular application on a pre-existing Node.js server?

I am currently working on an Angular 6 application that communicates with an existing Node.js API application. Up to this point, I have been using the following command to run and build my Angular application: ng serve Now, I am interested in serving m ...

The method `this.http.post(...).map` is not recognized as a valid function

doSelectMessagesAttributesUrl1(pushRequest : PushRequest) { console.info("sending post request"); let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded'}); return this.http .post(th ...

During rendering, the instance attempts to reference the "handleSelect" property or method which is not defined

I've incorporated the Element-UI NavMenu component into my web application to create a navigation bar using Vue.JS with TypeScript. In order to achieve this, I have created a Vue component within a directory called "navBar," which contains the follow ...

Unusual title attributed to saving the date in Firebase

Could anyone explain why my JSON appears like this https://i.stack.imgur.com/xzG6q.png Why does it have a strange name that starts with -M-yv... instead? I am saving my data using the http.post method, passing the URL to my database and an object to save ...

leveraging an npm package within an Angular 2 component

I'm facing some challenges trying to use an npm package called 'ip' in my Angular 4 component. The package can be found at https://www.npmjs.com/package/ip To add the package, I've executed the following commands: npm install ip --save ...

The function has been called but it did not return a

It seems that there is confusion surrounding the .toHaveBeenCalled() Matcher in Jasmine. While it should return a Promise that resolves when the function has been called, some users are experiencing it returning undefined instead. For example: it('sh ...

The function Interceptor.intercept is not defined

For a while now, I've been working on implementing an application-wide interceptor. However, no matter what I do, I keep encountering the same frustrating error: TypeError: this.interceptor.intercept is not a function After countless hours of debugg ...

Special scenarios requiring OnPush Change Detection

I'm currently building an Angular 2 application using ngrx, and I've been intrigued by the concept of OnPush change detection for optimizing performance. After reading multiple articles on the topic, it seems that the general consensus is: "If a ...

Guide to creating a type for a JSON object with nested properties in TypeScript

I have some JSON strings structured as follows: { name: 'test', url: 'http://test.org', contact: { email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0263636342766771762c616d6f" ...

Unable to locate 'reflect-metadata' module within Docker container on Production Server

I encountered an error: module.js:550 throw err; ^ Error: Cannot find module 'reflect-metadata' at Function.Module._resolveFilename (module.js:548:15) at Function.Module._load (module.js:475:25) at Module.require ( ...

Building a frontend and backend using Typescript with a shared folder for seamless integration

I am currently exploring the idea of transitioning to TypeScript, but I am facing challenges in figuring out how to create a shared folder between the frontend and backend. This is the project structure that I have come up with: frontend - src -- server.t ...