How to instantiate Httpclient in Angular 4 typescript?

Asked

Viewed 671 times

2

Based on this example for Http, I would like to know how to instantiate Httpclient:

 **constructor() {  
    const browserXhr: BrowserXhr = new BrowserXhr();  
    const baseResponseOptions: ResponseOptions = new ResponseOptions();  
    const xsrfStrategy: CookieXSRFStrategy = new CookieXSRFStrategy();  
    const backend: XHRBackend = new XHRBackend(browserXhr, baseResponseOptions, xsrfStrategy);  
    const requestOptions: RequestOptions = new RequestOptions();  
    const http: Http = new Http(backend, requestOptions);  
this._http = http;**  

Then I would like to know how to instantiate Httpclient in the same way.

Obs: the shape **constructor(private http: HttpClient) {}** does not serve me in this case because I need to instantiate within a class typescript and in this way or extending another class and keeps demanding the http as a parameter.

Some more current considerations...

I need to create a class that when instantiated I inform the name of the table that it will work but I don’t want to have to inform more parameters in the class constructor as I have to do currently as this example below (this is how it currently works):

@Injectable() 
export class MvsDbTable implements OnInit {
constructor( 
    @Inject('_tableName') public _tableName: string, 
    @Inject('_HTTP') public _HTTP: HttpClient  ) {}

So I urge the class on a service:

    public _tblFinances = new MvsDbTable('Finances', this._Http);

But I would like to not have to enter this parameter ", this.http".

Then I wish it were so:

@Injectable() 
export class MvsDbTable implements OnInit {
constructor( 
    @Inject('_tableName') public _tableName: string ) {
    this._HTTP = new HttpClient(this._Handler);   }     

Only it does not work instantiating the _Handler parameter because it is abstract so it cannot be instantiated.

Then I would instantiate the class in such a service:

    public _tblFinances = new MvsDbTable('Finances');

It just cleans up the code, the first way it works. What I try to figure out is how to instantiate Httpclient within the class without having to pass Httpclient as a parameter in the constructor as I did with Http which also worked.

Thank you

1 answer

1

Within the app.module.ts you can set how the previovider will be instantiated.

Create an object informing the class that will be provided (provide), the method that will do the new (useFactory) and the dependencies needed to create your class (deps):

import { FactoryProvider } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { HttpHandler } from '@angular/common/http';
import { HttpClientModule } from '@angular/common/http';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [
    <FactoryProvider>{
      provide: HttpClient, HttpClient ou sua classe que herda HttpClient
      useFactory: requestLoader,
      deps: [ HttpHandler ]
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

export function requestLoader(handler: HttpHandler) {
  return new HttpClient(handler); // HttpClient ou sua classe que herda HttpClient
}

This way you can use the constructor asking for the Httpclient service or its class that inherits Httpclient

Important: If your goal is to intercept requests to enter authorization tokens, for example, this is no longer the best way to do it from angle 4.3.4. This should be done using the interceptors (Example based on article building-http-Interceptor-angular-5):

app.modulets.:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { MyHttpInterceptor } from './myhttp.interceptor';

import { AppComponent } from './app.component';

@NgModule({
declarations: [
    AppComponent,
],
imports: [
    BrowserModule,
    HttpClientModule
],
providers: [
    {
    provide: HTTP_INTERCEPTORS,
    useClass: MyHttpInterceptor,
    multi: true
    }
],
bootstrap: [AppComponent]
})
export class AppModule { }

myhttp.interceptor.ts:

import { Injectable, Injector } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';

@Injectable()
export class MyHttpInterceptor implements HttpInterceptor {
    constructor() { }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        // logar para teste
        console.log('intercepted request ... ');

        // Clonar a requisição para adicionar o cabeçalho
        const authReq = req.clone(
            {
                headers: req.headers.set('headerName', 'headerValue')
            }
        );

        console.log('Sending request with new header now ...');

        // enviar a requisição modificada para a proxima classe da cadeia
        return next.handle(authReq)
            .catch((error, caught) => {
                // interceptar a resposta de erro e logar
                console.log('Error Occurred');
                console.log(error);
                // returnar o erro para o metodo que chamou
                return Observable.throw(error);
            }) as any;
    }
}
  • Marcelo, sorry for my delay but I had left the project a little aside and I only resumed now, unfortunately I had not seen your answer, I thank you very much for your help.

  • 1

    It didn’t work and it seems to me that there is a mix between http and httpclient in your code (unless I’m mistaken). But even if adapting to httpclient just didn’t work, httpclient to be instantiated asks for an Handler parameter, put it and call. GET is not executed. It gives no error or anything, it just generates error exception but without even making the Rest request. So I still need information on how to instantiate an Httpclient without having to inject it into the constructor. !

  • @Marcelovareladasilva sorry the delay to answer. There really was a problem in the sample code. I made the correction and added a few more details. Please make sure to answer your question.

  • Thanks again for answering. I made a modification in my question trying to clarify more my need, can review above.

  • I believe that in this your reply the part of requestLoader is the way of what I need but unfortunately I did not have the knowledge of how to implement your suggestion in my service, in the module I implemented right as suggested but could not use in the service, like in this example below that doesn’t work: @Injectable() export class Mvsdbtbl { constructor( @Inject('_tblName') public _tblName: string ) { this. _HTTP = requestLoader(); } Basically what I need is to instantiate Httpclient inside a class without using Dependency Injection. Thank you

  • What if you created a service with a generate method in which it receives the httpclient reference from the constructor and when you call the generate method it gives a new one in the Mvstable class by injecting http? The service would be a kind of Builder to abstract the need to create http client in hand (it would even receive Singleton http from the angular itself)

  • @Marcelovareladasilva @Injectable() export class Mvstablebuilderservice { constructor(private http: Httpclient) { } generate(tableName: string) ː Return new Mvsdbtable(tableName, this.http);} }

  • Sorry to keep you waiting, I’ve been pretty busy delivering a project. Yes, that’s how it works, the other day I thought about it but since I had another priority I hadn’t tried, now not to leave you unanswered I just tested and it really works, I didn’t want to keep running around but after the http migration (which I could instantiate) httpclient will have to be that way. It was very good, thank you very much for the suggestion. Hug!

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.