angular - ¿Cómo inyectar HttpClient en un método estático o clase personalizada?
Me gustaría usar Angular HttpClient en un método estático o clase (en la clase no se puede definir como parámetro del constructor).
Intenté algo como:
export class SomeNotInjectableService {
static doSomething() {
const injector = Injector.create({
providers: [{provide: HttpClient, deps:[]}]
});
const httpClient: HttpClient = injector.get(HttpClient);
httpClient.request(...); // error Cannot read property 'handle' of undefined
}
}
esto es un intento de inyectar manualmente el cliente en un método de servicio estático. No funciona. Tengo curiosidad de cómo hacer esto o cómo inyectar el cliente en un método normal pero en una clase que no es un componente.
Respuesta #1
También puedes omitir el inyector si no tienes uno. Eso significa hacer la 'inyección' tú mismo. No recomiendo hacer esto. Si realmente quieres usar un método estático (en lugar de un servicio adecuado), pasa todas las cosas necesarias.
No estoy seguro de si esto no es ya obvio, pero cualquier interceptor HTTP faltará en esta cadena de httpClient, ya que no hay forma de resolverlos.
import { HttpClient, HttpXhrBackend } from '@angular/common/http';
const httpClient = new HttpClient(new HttpXhrBackend({ build: () => new XMLHttpRequest() }));
httpClient.get('test').subscribe(r => console.log(r));
o usando tu propio inyector creado (si no te gusta pasar argumentos al constructor):
const injector = Injector.create({
providers: [
{ provide: HttpClient, deps: [HttpHandler] },
{ provide: HttpHandler, useValue: new HttpXhrBackend({ build: () => new XMLHttpRequest }) },
],
});
const httpClient: HttpClient = injector.get(HttpClient);
httpClient.get('test').subscribe(r => console.log(r));
Respuesta #2
No estoy exactamente seguro de por qué no funciona de la manera en que lo intentaste (probablemente falte algo al crear el inyector), pero funciona si usas un inyector 'inyectado'
Si miras el código fuente que lanza el error, verás que menciona controladores para la solicitud, los cuales parecen ser nulos en tu ejemplo. Tal vez Angular registra algunos controladores internos cuando el HttpClient se proporciona de la manera 'tradicional', pero no de la manera en que lo haces.
// Start with an Observable.of() the initial request, and run the handler (which
// includes all interceptors) inside a concatMap(). This way, the handler runs
// inside an Observable chain, which causes interceptors to be re-run on every
// subscription (this also makes retries re-run the handler, including interceptors).
var /** @type {?} */ events$ = rxjs_operator_concatMap.concatMap.call(rxjs_observable_of.of(req), function (req) { return _this.handler.handle(req); });
Solución alternativa:
app.module.ts
import {Injector} from '@angular/core';
export let InjectorInstance: Injector;
export class AppModule
{
constructor(private injector: Injector)
{
InjectorInstance = this.injector;
}
}
Tu clase/método estático
import {InjectorInstance} from './app.module';
export class SomeNotInjectableService {
static doSomething()
{
/* const injector = Injector.create({
providers: [{provide: HttpClient, deps:[]}]
});
const httpClient: HttpClient = injector.get(HttpClient);
*/
const httpClient = InjectorInstance.get<HttpClient>(HttpClient);
httpClient.request(...)...
}
}
Ejemplo en Stackblitz: https://stackblitz.com/edit/angular-li8b37?file=app%2Fapp.component.ts
