What is the best way to handle the completion of an HTTP request in Angular?

Struggling to grasp the concept of waiting for an observable to complete while learning Angular (Typescript) + ASP Net Core. I've set up a login service on the backend that's functioning correctly. However, I encountered an issue when trying to create a simple helper to streamline handling http responses on the client side. The problem arises as it runs twice: initially, it assumes RequestResponse is undefined (due to skipping the http request), but on the second run, RequestResponse is populated and works as intended.

Take a look at the Http helper below:

 get<T>(url: string): Observable<T> {
    let options = this.doHeaders();
    return this.doSub(this.http.get(this.doUrl(url), options));
}

private doSub<T>(obs: Observable<Response>) {
    var ob1: Observable<T> = obs.map(this.extractData)
        .catch(this.handleError);

    return ob1;
}

And here's the definition of RequestResponse:

export class RequestResponse {
   public error: string;
   public isOk: boolean;
   public code : StatusCode; 
}

Additionally, there's the Service implementation:

@(Injectable)
export class RequestService {

constructor(
    private net: NetworkService,
    private loaderService: LoaderService,
    private storage: StorageService,
) {
}

login(email: string, password: string, rememberMe: boolean = false): RequestResponse {
    var r = new RequestResponse();

     // Need to figure out how to make this wait
     this.net.get<LoginModel>(`Authentication/Login/${email}/${password}`).subscribe(t => {
            this.storage.token = t.token;
            this.storage.email = rememberMe ? email : null;
            this.storage.password = rememberMe ? password : null;
            r.isOk = true;
            r.code = StatusCode.OK;
        },
        error => {
            r.isOk = false;
            switch (error.message) {
            case '403':
                    r.code = StatusCode.Forbidden; r.error = 'You've been suspended'; return;
            case '404':
                    r.code = StatusCode.NotFound; r.error = 'User not found'; return;
            case '406':
                    r.code = StatusCode.NotAcceptable; r.error = 'Invalid Email/Password'; return;
            default:
                r.code = StatusCode.InternalServerError; r.error = 'Internal Error'; return;
            }
        });

    return r; // Issue with first response being null
   }
}

This is how I'm attempting to use it:

login() {

    this.loginResponse = this.requestService.login(this.email, this.password, this.rememberMe);
    console.log(this.loginResponse);
    if (!this.loginResponse.isOk) {
        this.toasterService.pop('error', 'Error', this.loginResponse.error);
        return;
    }
    this.router.navigateByUrl('/home');
}

Despite exploring Promises and Observables and making several adjustments, the initial RequestResponse being null continues to be a concern. Any suggestions on how to tackle this challenge?

Answer №1

It's advisable to handle the subscribe function within the component itself, rather than in the service. This approach allows for better responsiveness once the subscription is complete and provides options for cancellation or unsubscribing.

Here is an example of code from a service:

retrieveData(): Observable<IData[]> {
    return this.http.get<IData[] >(this.dataUrl)
                    .pipe(
                        tap(response => console.log(JSON.stringify(response))),
                        catchError(this.handleError)
                    );
}

Below is a snippet of code from a component:

ngOnInit(): void {
    this.dataService.retrieveData().subscribe(
        (data: IData[]) => {
            this.data = data;
            // Any additional tasks upon subscription completion can be included here
        },
        (error: any) => this.errorMsg = <any>error
    );
}

To view a fully functional sample application, visit my GitHub repository: https://github.com/JohnDoe/Angular-SampleApp

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

Incorporate TypeScript @types/ packages within the packages.json file

I have a question about the @types dependencies in the package.json file: According to the information provided in this URL, it is suggested to install types as runtime dependency npm install --save @types/lodash TS 2.x d.ts Consumption However, personal ...

The beforePopState event in next/router is not triggering as expected

Noticing an issue where the beforePopState event is not triggering when I use the back button. This code snippet is part of a hook defined in _app.js according to the documentation. The current version being used is 12.1.5 If anyone has insights on what ...

I am unable to transmit information using the `http.post` function

When attempting to send a post request to the backend, I am receiving a response code of 500 and an empty data object on the API side. Interestingly, using Postman gives successful results. return http.post(link,data,headers).subscribe(response=>{ ...

Modification of encapsulated class in Angular is not permitted

Within Angular, a div element with the class "container" is automatically created and inserted into my component's HTML. Is there a way to modify this class to "container-fluid"? I understand that Angular utilizes encapsulation, but I am unsure of how ...

In Angular 7, you can create a checklist from an array of objects by incorporating multiple selection and a "select all" feature. Here's how to

I need assistance with creating a list in Angular using ngFor. Each item must have a unique ID and a checkbox, as depicted in the diagram. However, I am struggling to determine how to manage multiple selections, implement a select all feature, and trigge ...

Frequency-focused audio visualization at the heart of the Audio API

Currently, I am developing a web-based audio visualizer that allows users to adjust the raw audio signal visualizer to a specific frequency, similar to the functionality found in hardware oscilloscopes. The goal is for the wave to remain stationary on the ...

The compiler encounters an issue when attempting to import a type from the global.d.ts

You can find the complete NPM package on GitHub here. tsconfig.json { "compilerOptions": { "target": "es5", "module": "commonjs" } } global.d.ts interface Foo { } index.ts const x: Foo = {}; When we try to build, we encounter this error: ...

Error encountered when utilizing cursor in Prisma

I am currently utilizing Prisma version 4.2.1 within a Next.js API Route to implement cursor-based pagination for posts. Upon passing the cursor to the API endpoint, I encounter an error message (500) in the console: TypeError: Cannot read properties of u ...

How can I enable email and password login in @auth0/auth0-angular?

Auth0 SDK for Angular Single Page Applications - the documentation outlines two methods for logging in: loginWithPopup loginWithRedirect Is there a possibility to add another option for logging in with just an email and password? ...

A guide on dynamically displaying Primeng Components within Angular applications

My task involves dynamically rendering Primeng components along with regular HTML elements. The template for rendering is stored as a string, as shown below: const dynamicTemplate = `<div class="card flex flex-row gap-3 justify-content-cen ...

When running `aws-cdk yarn synth -o /tmp/artifacts`, an error is thrown stating "ENOENT: no such file or directory, open '/tmp/artifacts/manifest.json'"

Starting a new aws-cdk project with the structure outlined below src └── cdk ├── config ├── index.ts ├── pipeline.ts └── stacks node_modules cdk.json package.json The package.json file looks like this: " ...

encountering a problem with angular-datatables implementation

I am currently using Ubuntu 20.04 with npm version 6.14.15, Node.js version 14.17.2, and Angular CLI version 11.2.14. To enhance my working directory, I decided to integrate a data table using the angular-datatables module. In order to successfully utiliz ...

Struggling with Navigation Guard integration in a Vue 3 + Quasar + TypeScript application

Currently, I am developing an application using the Quasar Framework in conjunction with Vue 3 and TypeScript, specifically utilizing the Composition API. My objective is to incorporate a Navigation Guard within my routes.ts file for handling route authent ...

Potential solution for communication issue between Angular CLI and Flask due to cross-origin error

Initially, the user id and password are submitted from the UI (angular) to Flask: public send_login(user){ console.log(user) return this.http.post(this.apiURL+'/login',JSON.stringify(user),this.httpOptions) .pip ...

Utilizing PrimeNG checkbox groups in a reactive form: A guide to retrieving all selected values

I am facing an issue with a group of <p-checkbox> elements from PrimeNG. They all have the same name and formControlName attributes. The form control's value is an array, but it seems to only retain the selection of the last checkbox clicked. T ...

How can you utilize Angular 2 Services for sharing global variables?

Within our NG starter boilerplate, the file app.component.ts contains the following code: export class AppComponent {title = "Website Title"} The title variable will be displayed in the appropriate app.component.html as shown below: <p>{{title}}&l ...

Stop webpack from stripping out the crypto module in the nodejs API

Working on a node-js API within an nx workspace, I encountered a challenge with using the core crypto node-js module. It seems like webpack might be stripping it out. The code snippet causing the issue is: crypto.getRandomValues(new Uint32Array(1))[0].toS ...

What is preventing TypeScript from identifying the type of a parent based on its child?

Take a moment to explore the following example: type Num = { type: 'NUMBER' numberValue: number } type Str = { type: 'STRING', stringValue: string } type B_Num = { a: Num; numberData: number; } type B_Str = { ...

Is Angular9 BehaviorSubject from rxjs giving trouble across different components?

I am facing an issue with updating data in real-time from the profile component to the header component. Initially, it works fine but after updating any value in the profile component, the header observable does not subscribe again. To solve this problem, ...

Using Protractor: Verifying if an input field is in focus and ready for text input

Is there a way to determine if an input field has focus? I attempted the following approach: in my .po.ts getEditInputField(fieldName: string) { return $(`input[data-e2e=${fieldName}]`) } In my .spec.ts it("should focus the Abschlag input field", ...