How to instantiate an Angular HttpClient?

How do you instantiate an HttpClient in Angular 5? I need to instantiate it inside the constructor, but not in this line constructor(private _Http: HttpClient).

Maybe something like this hypothetical example:

import { HttpClient, HttpHandler } from '@angular/common/http';
private _Http: HttpClient;
private _httpHandler: HttpHandler;
@Injectable()
export class DataService {
    constructor() {
        this._Http = new HttpClient(_httpHandler);
    }
}

Thank you

Upvotes: 14

Views: 24446

Answers (2)

mtareq
mtareq

Reputation: 181

As previous answers stated, it's better to use dependency injection. That's being said, you can create instance manually like below

const httpClient = new HttpClient(new HttpXhrBackend({ 
    build: () => new XMLHttpRequest() 
}));

Upvotes: 15

vince
vince

Reputation: 8306

You should really use dependency injection, since it's very clean and easy:

constructor(private http: HttpClient) {}

That's how the HttpClient and all Angular services are intended to be used. Read more about DI here: https://angular.io/guide/dependency-injection.

However, you can technically do it without DI, since it is just a class.

The issue with what you're currently doing with this._Http = new HttpClient(_httpHandler); is that the HttpClient requires an instance of an HttpHandler, but right now it's just getting a variable with no value called _httpHandler typed as an HttpHandler. You need to do this:

let _httpHandler = new HttpHandler();

@Injectable()
export class DataService {
    constructor() {
        this._Http = new HttpClient(_httpHandler);
    }
}

That should get it to "work", but again I'd recommend taking another look at dependency injection.

UPDATE:

So as Jota. Toledo pointed out in the comments, you actually cannot instantiate an HttpHandler as it is an abstract class. See the source code here: https://github.com/angular/angular/blob/5.2.1/packages/common/http/src/backend.ts#L12-L27.

So this just got a lot more complicated.

For @Component's, there is a way to work with injectors directly that the Angular team explicitly advises against.

In your @Component metadata, provide the service you want to use directly (in the providers array), like so:

@Component({
 providers: [HttpClient]
}
export class MyComponent {}

And then you can inject the Injector using cough Dependency Injection. And access your providers in the constructor like so:

constructor(private injector: Injector) {
  this._http = injector.get(HttpClient);
}

Although, I don't think this will work for your use case considering you show an @Injectable in your question, which doesn't have metadata per se. Second, you're already using dependency injection to get ahold of the Injector so you might as well just use DI for HttpClient.

It seems you can also still use the deprecated ReflectiveInjector to do this with an @Injectable class.

In conclusion, this is a wild goose chase and you should really use dependency injection. It is a fundamental concept in Angular and one of the things that makes the framework so useful. If for some reason you cannot use it, you may want to look at other options besides Angular.

Upvotes: 4

Related Questions