admin管理员组

文章数量:1122846

I want to use a simple method to check for internet connectivity. We have a file hosted on a server and I simply want to check that we can see it.

The file contains:

{
    "status": "success"
}

In my Angular component:

#http = inject(HttpClient);
isOnline: boolean;

updateOnlineStatus(url: string): void {
    console.log(this.#CLASS_NAME + '.updateOnlineStatus() - url', url);
    
    this.#http.get<any>(url).pipe(
        catchError((error) => {
            console.log(this.#CLASS_NAME + '.updateOnlineStatus(), error', error);
            this.isOnline = false;
            return of(null);
        })
    ).subscribe(response => {
        if (response && response.status === 'success') {
            this.isOnline = true;
        } else {
            this.isOnline = false;
        }
    });
}

But when I call the method, I get:

LoginPage.updateOnlineStatus() - url https://xxx/status.json
loginponent.ts:288 LoginPage.updateOnlineStatus(), error TypeError: Cannot read 
properties of undefined (reading 'length')
at HttpHeaders.applyUpdate (http.mjs:222:27)
at http.mjs:195:58
at Array.forEach (<anonymous>)
at HttpHeaders.init (http.mjs:195:33)
at HttpHeaders.forEach (http.mjs:263:14)
at Observable._subscribe (http.mjs:2116:29)
at Observable._trySubscribe (Observable.js:37:25)
at Observable.js:31:30
at errorContext (errorContext.js:19:9)
at Observable.subscribe (Observable.js:22:21)

And on the network tab, I can see that the GET is not executed so it looks as though HttpClient is failing before then.

What am I doing wrong?

The file exists and I can see it using Postman or even the browser (but the request isn't even executing).

I want to use a simple method to check for internet connectivity. We have a file hosted on a server and I simply want to check that we can see it.

The file contains:

{
    "status": "success"
}

In my Angular component:

#http = inject(HttpClient);
isOnline: boolean;

updateOnlineStatus(url: string): void {
    console.log(this.#CLASS_NAME + '.updateOnlineStatus() - url', url);
    
    this.#http.get<any>(url).pipe(
        catchError((error) => {
            console.log(this.#CLASS_NAME + '.updateOnlineStatus(), error', error);
            this.isOnline = false;
            return of(null);
        })
    ).subscribe(response => {
        if (response && response.status === 'success') {
            this.isOnline = true;
        } else {
            this.isOnline = false;
        }
    });
}

But when I call the method, I get:

LoginPage.updateOnlineStatus() - url https://xxx/status.json
login.component.ts:288 LoginPage.updateOnlineStatus(), error TypeError: Cannot read 
properties of undefined (reading 'length')
at HttpHeaders.applyUpdate (http.mjs:222:27)
at http.mjs:195:58
at Array.forEach (<anonymous>)
at HttpHeaders.init (http.mjs:195:33)
at HttpHeaders.forEach (http.mjs:263:14)
at Observable._subscribe (http.mjs:2116:29)
at Observable._trySubscribe (Observable.js:37:25)
at Observable.js:31:30
at errorContext (errorContext.js:19:9)
at Observable.subscribe (Observable.js:22:21)

And on the network tab, I can see that the GET is not executed so it looks as though HttpClient is failing before then.

What am I doing wrong?

The file exists and I can see it using Postman or even the browser (but the request isn't even executing).

Share Improve this question edited Nov 21, 2024 at 14:29 JSON Derulo 17.2k11 gold badges56 silver badges73 bronze badges asked Nov 21, 2024 at 10:32 Rob MousleyRob Mousley 1111 silver badge6 bronze badges 1
  • 1 Looks like the request headers can not be constructed properly. Are there any interceptors in your app which mess with the request headers? – JSON Derulo Commented Nov 21, 2024 at 10:33
Add a comment  | 

2 Answers 2

Reset to default 1

The code for creating the request looks fine. The stack trace of the error points to the creation of the request headers, however you have not added any additional headers to this request.

So there must be something else in your app which messes with the request and somehow makes the headers invalid. Usually this happens in interceptors. To find the interceptors in your app, search for the HTTP_INTERCEPTORS injection token or the withInterceptors function.

After you found the interceptors, you can remove them temporarily one by one to see which one causes the issues. Finally, you can fix the interceptor's logic.

Thanks to JSON Derulo who pointed me to the cause of the problem. Our final solution was to use HTTPBackend to bypass any interceptors and avoid having dependencies in the HTTPInterceptor code. I ended up with the following service.

/**
 * @service NetworkService
 * 
 * @description
 * This service is used to check whether the Angular application is connected to the internet
 * by requesting a given status.json file from the server. It avoids any HTTP interceptors 
 * by using HttpBackend to make requests. The service provides a public boolean `isOnline` 
 * that can be accessed from any component to determine the current internet connection status.
 * 
 * Usage:
 * 1. Inject `NetworkService` into your component.
 * 2. Call `await updateOnlineStatus(url: string)` to update the online status.
 * 3. Check `isOnline` to determine the internet status and take appropriate actions.
 */

import { inject, Injectable } from '@angular/core';
import { HttpBackend, HttpClient } from '@angular/common/http';
import { catchError } from 'rxjs/operators';
import { of, lastValueFrom } from 'rxjs';

@Injectable({
    providedIn: 'root'
})
export class NetworkService {
    readonly #CLASS_NAME = 'NetworkService';
    public isOnline: boolean = false;

    #httpRaw: HttpClient;
    #httpBackend = inject(HttpBackend);

    constructor() {
        console.log(this.#CLASS_NAME + 'constructor()');
        this.#httpRaw = new HttpClient(this.#httpBackend);
    }

    /**
     * Updates the online status of the application by attempting to fetch the 
     * given status.json URL.
     *
     * @param {string} url - The URL of the status.json file to check the network status.
     * @returns {Promise<void>} A promise that resolves once the online status has been updated.
     */
    public async updateOnlineStatus(url: string): Promise<void> {
        console.log(this.#CLASS_NAME + '.updateOnlineStatus() - url:', url);
        try {
            const response = await lastValueFrom(this.#httpRaw.get<{ status: string }>(url).pipe(
                catchError(() => {
                    this.isOnline = false;
                    return of(null);
                })
            ));
            console.log(this.#CLASS_NAME + '.updateOnlineStatus() - response:', response);
            
            if (response) {
                this.isOnline = response.status === 'success';
            }
        } catch (error) {
            console.log(this.#CLASS_NAME + '.updateOnlineStatus() - error:', error);
            this.isOnline = false;
        }
    }
} 

本文标签: angularHTTP GET throws TypeError Cannot read properties of undefined (reading 39length39)Stack Overflow