Tips for managing and identifying canceled requests in an Angular HTTP interceptor

Having trouble handling cancelled requests in my http interceptor. Despite trying various methods from SO, I can't seem to catch it.

Here is an example of how my interceptor looks:

public intercept(req: HttpRequest<any>, next: HttpHandler) {
        const xyz = this._cookieService.get('xyz');
        const abc = this._cookieService.get('abc');

        let authReq;
        if (jwt === "undefined" || jwt === undefined) {
            authReq = req.clone({ headers: req.headers.set('Authorization', xyz) });
        } else {
            authReq = req.clone({setHeaders: { Authorization: 'bearer ' + abc } });
        }

        return next
            .handle(authReq)
            .pipe(
                catchError((err: HttpErrorResponse) => this.catchErrorHandler(err))
            );
    }

I've experimented with the do and finalize methods but still facing issues. Whenever my authentication expires, subsequent requests start failing one by one, causing the page to break. I'm looking for a solution in code to prevent this happening.

Some methods I've tried:

https://i.sstatic.net/vuHKA.png

Answer №1

One important operator in RxJS is known as finalize.

This operator returns an Observable that behaves like the source Observable, but with the added functionality of executing a specified function when the source completes either successfully or with an error. The specified function will also run if the subscriber explicitly unsubscribes.

    return next
        .handle(authReq)
        .pipe(
            catchError((err: HttpErrorResponse) => this.catchErrorHandler(err)),
            finalize(() => console.log('finalize'))
        );

Answer №2

Here is a suggestion for an interceptor you can use:

@Injectable()
export class RequestInterception implements HttpInterceptor {
  public constructor() { }

  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    const token = '';
    const currentLanguage = 'en';
    let headers;

    if (token) {
      headers = new HttpHeaders({
        "X-MDM-Token": token,
        "Accept-Language": currentLanguage
      });
    }

    request = request.clone({
      headers: headers,
      url: request.url || environment.serverUrl
    });

    return next.handle(request).pipe(
      map((event: any) => {

        if (event.status < 200 || event.status >= 300) {
          return Observable.throw(event);
        }

        return event;
      }),

      catchError((response: HttpErrorResponse, request) => {
        switch (response.status) {
          case 401:
            //
            break;
        }
        return throwError("Server Error with RequestInterception!");
      })
    );
  }
}

If the client cancels the HTTP request and receives a 499 HTTP code, it will be captured by:

if (event.status < 200 || event.status >= 300) {
      return Observable.throw(event);
}

Answer №3

I've been curious about this for a while, so I decided to explore it further today.

When dealing with a cancelled request, the error message typically appears as follows:

{
    "headers": {
        "normalizedNames": {},
        "lazyUpdate": null,
        "headers": {}
    },
    "status": 0,
    "statusText": "Unknown Error",
    "url": "https://localhost:7258/api/company/test-exception",
    "ok": false,
    "name": "HttpErrorResponse",
    "message": "Http failure response for https://localhost:7258/api/company/test-exception: 0 Unknown Error",
    "error": {
        "isTrusted": true
    }
}

Note that the headers are empty and the status code is 0.

Upon researching what status code 0 signifies, I came across the following insights:

In practical terms, status==0 in a failed XmlHttpRequest should be viewed as an undefined error.

This code might indicate an error occurring even before communication with the server takes place.

Response by whitneyland on What does it mean when an HTTP request returns status code 0?

While we still need to pinpoint the root cause of the status 0, we can handle this error simply by:

next
  .handle(req)
  .pipe(
  catchError((err) => {
    if (err.status == 0) {
      // handle cancelled request here
      console.log(err);
    }
  }
})

Answer №4

This is how I accomplished it:

Interceptor code:

...
return next.handle(request)
  .pipe(
    onCancelled(() => {
      // callback for cancelled requests
    }),
  );
...

onCancelled function

function onCancelled<T>(callback: () => void) {
  return (obs: Observable<T>) => {
    let cancelled = true;
    return new Observable<T>(subscriber => {
      const sub = obs.subscribe(
        value => {
          if (value instanceof HttpResponse) cancelled = false;
          subscriber.next(value);
        },
        err => {
          cancelled = false;
          subscriber.error(err);
        },
        () => {
          cancelled = false;
          subscriber.complete();
        });
      return () => {
        if (cancelled) callback();
        sub.unsubscribe();
      };
    });
  };
}

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

Eliminate Angular Firebase Object and Storage

Currently in the final stages of completing my initial project using Angular and Firebase. I have encountered a query regarding the deletion of objects utilizing both technologies. My service is designed to delete an object that contains a nested object n ...

Instead of being viewed in the browser, the CSV file is being downloaded

I'm currently using Jhipster and have a function generated by Jhipster to open files in the browser. However, I'm facing an issue with this function when it comes to opening CSV files - instead of opening in the browser, they are being downloaded ...

In relation to the characteristics of an Angular Component (written in TypeScript) Class

I am attempting to create a circle on a canvas using Angular. I have followed the necessary steps and have a basic understanding of how everything works. Although my IDE is not showing any errors, when I run the code, the console displays an error stating ...

What is the best way to import modules with the "@" symbol in their path when working with Node.js?

Situation In my VueJS project, I have created service modules for use with vue cli. My code makes use of the @ symbol to easily access files within the src folder: /* Inside someService.js */ import API from '@/services/APIService.js' Ch ...

Endless scrolling feature malfunctioning

On my profile_page.php, the default setting is to display 10 posts (10 rows from the database) for the user. If a user has more than 10 posts, and scrolls to the bottom of the page, the div should expand to reveal the remaining posts (maximum of 10). For e ...

iOS iframe remains unscrollable only when switching from portrait to landscape orientation

I have a scrollable iframe set up on iOS like this: <div style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; overflow: scroll; -webkit-overflow-scroll: touch; ..."> <iframe style="height: 600px, ..."> </iframe> </d ...

Tips for adjusting the horizontal position of a grid item within a map() loop

I am trying to align the text in my Timeline component from Material Ui always towards the center of the timeline. The TimelineContent contains Paper, Typography (for title and description), and an image. Currently, I have multiple TimelineContent element ...

Distinguishing between keydown.enter for textareas in Angular on mobile and desktop devices

As I work on developing a chat platform, one of the key features is the message input box using a textarea where users can type their messages. Currently, pressing the Enter key allows the user to send a message. However, I am curious to explore if it&apos ...

Creating a transcluding element directive in AngularJS that retains attribute directives and allows for the addition of new ones

I've been grappling with this problem for the past two days. It seems like it should have a simpler solution. Issue Description The objective is to develop a directive that can be used in the following manner: <my-directive ng-something="somethi ...

Issue with VS code/Angular where linter is unable to detect components imported from shared modules

Having an issue with Angular materials components in my project. I have a shared module where I import all the necessary Angular materials modules, and the code runs fine. However, in my html files in VS Code, I see red squiggly lines under every Angular m ...

Comparison of Transform plugin and Syntax plugin within Babel

I am interested in incorporating Class properties into my webpack configuration. While following a tutorial on the website (www.survivejs.com), I came across two plugins being added to the .babelrc file: babel-plugin-syntax-class-properties and babel-plugi ...

``Can you provide guidance on excluding matching values from a dictionary object in a Angular project?

I've developed a function that takes a dictionary object and matches an array as shown below: const dict = { CheckAStatus: "PASS", CheckAHeading: "", CheckADetail: "", CheckBStatus: "FAIL", CheckBHeading: "Heading1", CheckCStatus: "FAIL", ...

Determining if a div is scrolled to the bottom in ASP.NET

Seeking help as I am unsure how to tackle this task. My project involves using asp.net, where I have a div that has overflow:auto enabled to display terms and agreements. Additionally, there is an asp.net checkbox control with visibility set to "false". ...

Identify the appearance of a web component being added to the Document Object

After reading this discussion regarding a web-component I created: <my-vue-web-comp [userId]="1" id="my-component"></my-vue-web-comp> The component functions properly in Angular. How can I determine when the web component h ...

What is the best way to utilize Link navigation in order to navigate away from a blocked route in the latest version of Next.js,

DISCLAIMER: I raised this issue on the Next.js GitHub repository, but it was closed without recognition. The solution provided did not resolve my problem, leading me to seek help here. The Issue at Hand I have created a demo app (accessible here) on Code ...

What is the best way to ensure that two objects collide with one another?

Issue Description I am currently working on implementing collision detection for two objects. The goal is to determine if the objects are intersecting by calculating their bounding boxes with Box3 and using the .intersectsBox() function to obtain a boolea ...

Receiving an Error 404 "not found" when making a Node.js POST Request using an Angular application

I have been working on developing an API with Node.js that connects to an SQL Server database. While my GET requests are functioning properly, I am encountering errors with my POST request. To organize my node project, I have split it into two files - a ro ...

Having difficulty with a button in a Navbar using Python and Selenium

As a newcomer to Selenium, I am currently attempting to automate the login process for a specific site but have hit a roadblock with clicking on the drop-down button in the navigation bar. Below is my current code: from selenium import webdriver from sel ...

Retrieve all users using Auth0 with Angular 2

I am trying to retrieve all users from auth0 using angular2 by following the documentation provided at https://auth0.com/docs/api/management/v2#!/Users/get_users. Here is what I have attempted so far. I understand that I need to include the access token, ...

Typescript: Shifting an image to the left and then returning it to the right

As a newcomer to Typescript, JavaScript, and front-end development, I am experimenting with creating a simulation of an AI opponent's "thinking" process when playing cards in a game. The idea is to visually represent the AI's decision-making by s ...