Can a custom subscribe() method be implemented for Angular 2's http service?

Trying my hand at angular2, I discovered the necessity of using the subscribe() method to fetch the results from a get or post method:

this.http.post(path, item).subscribe(
  (response: Response)=> {console.log(response)},
  (error: any)=>{console.log(error)}
);

However, I had the idea of enhancing the subscribe() method by creating a custom version that includes an error callback function with a strongly typed error argument. This would allow us to subscribe to the Observable in the following manner:

this.http.post(path, item).subscribe(
  (response: Response)=> {console.log(response)},
  (error: HttpError)=>{console.log(error.body)}
);

I defined the structure of HttpError as shown below:

import { ModelState } from "app/Base/model-state";
import { ModelStateDictionary } from "app/Base/model-state-dictionary";
import { ErrorBody } from "app/Base/error-body";

export class HttpError {
    public ok: boolean;
    public status: number;
    public statusText: string;
    public type: number;
    public url: string;
    public body: ErrorBody;
    public static create(error: any): HttpError {
        let errorBody: ErrorBody = new ErrorBody();
        let body = JSON.parse(error._body)
        errorBody.message = body.message == null ? "" : body.message;
        errorBody.modelStateDictionary = new ModelStateDictionary();
        if (body.modelState != null) {
            for (let key in body.modelState) {
                let modelState: ModelState = new ModelState();
                modelState.Value = key;
                for (let value in body.modelState[key]) {
                    modelState.Error.push(value);
                }
                errorBody.modelStateDictionary.push(modelState);
            }
        }
        let httpError: HttpError = new HttpError();
        httpError.body = errorBody;
        httpError.ok = error.ok;
        httpError.status = error.status;
        httpError.statusText = error.statusText;
        httpError.type = error.type;
        httpError.url = error.url;
        return httpError;
    }
}

To handle this conversion and ensure users can benefit from the improved version of subscribe(), I believe I need to invoke the create() method prior to subscription and transform the Java object error into an instance of HttpError. It seems like I might need to implement a custom Observable or utilize map(). As a newcomer to TypeScript and Reactive programming, I would appreciate some guidance on how to accomplish this conversion effectively.

Answer №1

Initially, my understanding is that http.post in Angular essentially wraps the HTTP response. This snippet is extracted from the Angular source code.

function httpRequest(backend: ConnectionBackend, request: Request): Observable<Response> {
  return backend.createConnection(request).response;
}

In this context, either 'response' or 'error' refers to the actual HTTP response object.

this.http.post(path, item).subscribe(
  (response: Response)=> {console.log(response)},
  (error: any)=>{console.log(error)}
);

It might be beneficial to extend a method within Observable to customize the response handling and retrieve the desired Object. For example, using something like this.http.post(path, item).castHttpError().subscribe()

https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/subscribe.md

However, caution is advised when extending functionalities of established libraries like Angular. While creating your own distribution of Angular is discouraged by Angular itself, it could still be worth experimentation.

Lastly, I recommend crafting a utility method for implementing this operation, even though it may seem unnecessary, it won't cause harm.

this.http.post(path, item).subscribe(
  response => { console.log(response); },
  error => {
    console.log(toHttpError(error).body);
  }
);

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

Using TypeScript's `async await` within a nested function invocation

I am having trouble extracting the 'assigned suspect' from the callbacks, as it is showing up as undefined. Strangely, it works fine within an if statement. I believe the issue is related to the await/async functionality. Any assistance would be ...

Issues arise with the escape key functionality when attempting to close an Angular modal

I have a component called Escrituracao that handles a client's billing information. It utilizes a mat-table to display all the necessary data. When creating a new bill, a modal window, known as CadastrarLancamentoComponent, is opened: openModalLancame ...

Customizing a side menu by assigning a function to a specific option

Hello there! I am a newcomer to TypeScript and Ionic. I am trying to implement a function that clears the cart when the "Mercado" option in the side menu is clicked, but I am struggling to retrieve the page data. The code snippet below shows my attempt to ...

Is there a method to obtain the compiled CSS for an Angular 2+ component?

Is it possible to retrieve compiled CSS (as a string) from an Angular2+ component? @Component({ selector: 'test-graph', templateUrl: './test-graph.component.html', styleUrls: ['./test-graph.component.scss'] }) export cla ...

Issues with NgFor directive not functioning properly within a Bootstrap class in Angular 6

In my Angular project, I have successfully implemented a REST service. The film data is displayed as a JSON object below the image. However, I am facing an issue with printing the results inside the boxes using ngIf. Strangely, it works fine with ngFor exc ...

Issue encountered: Cannot locate module: Error message - Unable to find 'stream' in 'C:devjszip-test ode_modulesjsziplib' folder

I am encountering an issue in my angular 7 application while using jszip v3.2.1. During the project build process (e.g., running npm start), I receive the following error message: ERROR in ./node_modules/jszip/lib/readable-stream-browser.js Module not fo ...

Creating conditional observable debounceTime

I've implemented a basic debounce on an input element event in the following way: Observable .fromEvent(this.elInput.nativeElement, 'input') .debounceTime(2000) .subscribe(event => this.onInput(event)); Is there ...

Encountering an error while trying to update an Angular application to version 10

I am currently running a demo app and I am new to Angular. Below is my category list component. import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { Observable } from 'rxjs'; im ...

What is the best way to find the common keys among elements in a tuple type?

type Tuple=[{a:string,x:string,z:string},{b:string,x:string,z:string}] type IntersectionOfTupleElementKeys<T>=... type MyType = IntersectionOfTupleElementKeys<Tuple> // = ('a'|'x'|'z')&('b'|'x&ap ...

What is the process for combining two interface declarations into a single interface?

I have a question regarding organizing the properties of an interface: export interface IInvoicesData { invoice: IInvoice; invoiceWithTotals: IInvoice & IInvoiceTotals; } Currently, everything is functioning smoothly and I am able to consolid ...

Import Information into Popup Window

When a user clicks on the "view" button, only the details of the corresponding challenge should be displayed: Currently, clicking on the "view" button loads all the challenges. This is because in my view-one-challenge.component.html, I have coded it as fo ...

What is the best way to implement a dynamic templateUrl for an Angular 2 Component?

My goal is to dynamically load a component's templateUrl based on a value passed from the parent component. I understand that this can be achieved by using property binding to pass the value through @Input. Below, I have provided an example where the ...

Obtaining data attributes in Angular 8

I'm working with Angular 8 and I came across an issue. In my code snippet, there are two data attributes assigned to a button element, but only one attribute is showing up. Is this a syntax error or a bug? <button [attr.data-popolamento]="all" [a ...

Having trouble getting tailwind dark mode to work on next.js?

I have set up a custom boilerplate using next.js(10.0.5) with preact(10.5.12), typescript(4.1.3), and tailwind(2.0.2). I am attempting to incorporate a dark mode feature from Tailwind. I followed the instructions from next-themes in order to add the dark ...

toggle visibility on click using Angular

Within my Angular application, there is a plus button: <div style="display:inline-block;text-align:left;margin-bottom:2vh;" class="col-md-10 col-md-offset-2"> <button type="button" class="btn btn-default" (click)="MoreSentences(result.w ...

Unable to store object data within an Angular component

This is a sample component class: export class AppComponent { categories = { country: [], author: [] } constructor(){} getOptions(options) { options.forEach(option => { const key = option.name; this.categories[k ...

How can we reduce the size of a JSON object in Typescript before sending it to the client?

Currently, I am faced with a common challenge. I have a database object that is a standard JS object originating from a document database, and my goal is to transmit this object to the client. However, certain fields contain sensitive information that shou ...

How can we incorporate methods using TypeScript?

I'm currently diving into TypeScript and encountering some challenges when trying to incorporate new methods into the DOM or other pre-existing objects. For instance, I'm attempting to implement a method that can be utilized to display colored te ...

Defining onClick event in Typescript and React.Konva

Struggling with resolving the tslint error Type declaration of 'any' loses type-safety., particularly when it comes to determining the correct type for the Event. Currently converting the Lynda tutorial "Building and Deploying a Full-Stack React ...

The process of unit testing a component to verify the presence of a specific component on the page

Presenting my straightforward custom component dubbed as NavbarComponent with the selector app-navbar. This component serves as a basic static navbar and is being displayed in app.component.html: app.component.html <app-navbar></app-navbar> &l ...