navigationend - router events subscribe angular 4
Cómo extender la clase http 2 angular en Angular 2 final (6)
Creo que la respuesta de peeskillet debería ser la respuesta seleccionada, así que lo que estoy poniendo aquí solo pretende aumentar su respuesta en lugar de competir con ella, pero también quería dar un ejemplo concreto ya que no creo que sea 100% obvio exactamente a qué código se traduce la respuesta de peeskillet.
app.module.ts
siguiente en la sección de providers
de mi app.module.ts
. Estoy llamando a mi reemplazo de Http
personalizado MyHttp
.
Observe cómo, como dijo peeskillet, sería provide: Http
, no provide: MyHttp
.
providers: [
AUTH_PROVIDERS
{
provide: Http,
useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => {
return new MyHttp(backend, defaultOptions);
},
deps: [XHRBackend, RequestOptions]
}
],
Entonces mi clase de extensión Http
se define así:
import { Injectable } from ''@angular/core'';
import { Http } from ''@angular/http'';
@Injectable()
export class MyHttp extends Http {
get(url: string, options?: any) {
// This is pointless but you get the idea
console.log(''MyHttp'');
return super.get(url, options);
}
}
No es necesario hacer nada especial para que su aplicación use MyHttp
lugar de Http
.
Estoy intentando ampliar la clase http de angular 2 para poder manejar errores globales y configurar encabezados para mi servicio secureHttp. Encontré algunas soluciones pero no funciona con la versión final de Angular 2. Aquí está mi código:
Archivo: secureHttp.service.ts
import { Injectable } from ''@angular/core'';
import { Http, ConnectionBackend, Headers, RequestOptions, Response, RequestOptionsArgs} from ''@angular/http'';
@Injectable()
export class SecureHttpService extends Http {
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) {
super(backend, defaultOptions);
}
}
Archivo: app.module.ts
import { BrowserModule, Title } from ''@angular/platform-browser'';
import { NgModule } from ''@angular/core'';
import { routing } from ''./app.routes'';
import { AppComponent } from ''./app.component'';
import { HttpModule, Http, XHRBackend, RequestOptions } from ''@angular/http'';
import { CoreModule } from ''./core/core.module'';
import {SecureHttpService} from ''./config/secure-http.service''
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
CoreModule,
routing,
HttpModule,
],
providers: [
{
provide: Http,
useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => {
return new SecureHttpService(backend, defaultOptions);
},
deps: [ XHRBackend, RequestOptions]
}, Title, SecureHttpService],
bootstrap: [AppComponent],
})
export class AppModule { }
componente.ts
constructor(private titleService: Title, private _secure: SecureHttpService) {}
ngOnInit() {
this.titleService.setTitle(''Dashboard'');
this._secure.get(''http://api.example.local'')
.map(res => res.json())
.subscribe(
data => console.log(data) ,
err => console.log(err),
() => console.log(''Request Complete'')
);
}
Por ahora me devuelve un error ''¡Ningún proveedor para ConnectionBackend!''. ¡Gracias por la ayuda!
Desde Angular 4.3, ya no necesitamos extends http
. En su lugar, podemos usar HttpInterceptor
y HttpClient
para archivar todas estas cosas.
Es similar y más fácil que usar Http
.
Emigré a HttpClient en aproximadamente 2 horas.
El detalle esta here
El motivo del error es porque está intentando proporcionar SecureHttpService
providers: [SecureHttpService]
Lo que esto significa es que Angular intentará crear la instancia, sin usar su fábrica. Y no tiene un proveedor registrado con el token ConnectionBackend
para dar a su constructor.
Podría eliminar el SecureHttpService
de los providers
, pero eso le dará otro error (que supongo que es por lo que lo agregó en primer lugar). El error será algo así como "no hay proveedor para SecureHttpService" porque está intentando inyectarlo en su constructor
constructor(private titleService: Title, private _secure: SecureHttpService) {}
Aquí es donde necesitas entender sobre tokens. Lo que usted proporciona como el valor a provide
es el token .
{
provide: Http,
useFactory: ()
}
El token es lo que se nos permite inyectar. Por lo tanto, puede inyectar el Http
y usará su SecureHttpService
creado. Pero esto te quitará cualquier posibilidad que tengas de usar el Http
regular, si alguna vez lo necesitas.
constructor(private titleService: Title, private _secure: Http) {}
Si no necesita saber nada sobre el SecureHttpService
, entonces puede dejarlo así.
Si desea poder inyectar realmente el tipo SecureHttpService
(tal vez necesite alguna API o quizás desee utilizar el Http
normal en otro lugar), simplemente cambie la provide
{
provide: SecureHttpService,
useFactory: ()
}
Ahora puede inyectar tanto el Http
regular como su SecureHttpService
. Y no olvide eliminar el SecureHttpService
de los providers
.
En realidad, solo puede extender el Http en su propia clase y luego usar una fábrica personalizada para proporcionar Http como eso:
luego, en mis Proveedores de aplicaciones pude usar una Fábrica personalizada para proporcionar ''Http''
importar {RequestOptions, Http, XHRBackend} desde ''@ angular / http'';
class HttpClient extends Http {
/*
insert your extended logic here. In my case I override request to
always add my access token to the headers, then I just call the super
*/
request(req: string|Request, options?: RequestOptionsArgs): Observable<Response> {
options = this._setCustomHeaders(options);
// Note this does not take into account where req is a url string
return super.request(new Request(mergeOptions(this._defaultOptions,options, req.method, req.url)))
}
}
}
function httpClientFactory(xhrBackend: XHRBackend, requestOptions: RequestOptions): Http {
return new HttpClient(xhrBackend, requestOptions);
}
@NgModule({
imports:[
FormsModule,
BrowserModule,
],
declarations: APP_DECLARATIONS,
bootstrap:[AppComponent],
providers:[
{ provide: Http, useFactory: httpClientFactory, deps: [XHRBackend, RequestOptions]}
],
})
export class AppModule {
constructor(){
}
}
con este enfoque no necesita anular ninguna de las funciones Http que no desea cambiar
Puede consultar https://www.illucit.com/blog/2016/03/angular2-http-authentication-interceptor/ que le ayudará.
Cambie sus proveedores como se muestra a continuación para obtener el último lanzamiento y verifíquelo:
providers: [
{
provide: SecureHttpService,
useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => {
return new SecureHttpService(backend, defaultOptions);
},
deps: [ XHRBackend, RequestOptions]
},
Title
]
Vea mi article sobre cómo extender la clase Http para Angular 2.1.1
Primero, vamos a crear nuestra clase de proveedor http personalizada.
http.service.ts
import {Injectable} from ''@angular/core'';
import {Http, XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Headers} from ''@angular/http'';
import {Observable} from ''rxjs/Observable'';
import ''rxjs/add/operator/map'';
import ''rxjs/add/operator/catch'';
@Injectable()
export class HttpService extends Http {
constructor (backend: XHRBackend, options: RequestOptions) {
let token = localStorage.getItem(''auth_token''); // your custom token getter function here
options.headers.set(''Authorization'', `Bearer ${token}`);
super(backend, options);
}
request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {
let token = localStorage.getItem(''auth_token'');
if (typeof url === ''string'') { // meaning we have to add the token to the options, not in url
if (!options) {
// let''s make option object
options = {headers: new Headers()};
}
options.headers.set(''Authorization'', `Bearer ${token}`);
} else {
// we have to add the token to the url object
url.headers.set(''Authorization'', `Bearer ${token}`);
}
return super.request(url, options).catch(this.catchAuthError(this));
}
private catchAuthError (self: HttpService) {
// we have to pass HttpService''s own instance here as `self`
return (res: Response) => {
console.log(res);
if (res.status === 401 || res.status === 403) {
// if not authenticated
console.log(res);
}
return Observable.throw(res);
};
}
}
Ahora, necesitamos configurar nuestro módulo principal para proporcionar XHRBackend a nuestra clase http personalizada. En su declaración del módulo principal, agregue lo siguiente a la matriz de proveedores:
app.module.ts
import { HttpModule, RequestOptions, XHRBackend } from ''@angular/http'';
import { HttpService } from ''./services/http.service'';
...
@NgModule({
imports: [..],
providers: [
{
provide: HttpService,
useFactory: (backend: XHRBackend, options: RequestOptions) => {
return new HttpService(backend, options);
},
deps: [XHRBackend, RequestOptions]
}
],
bootstrap: [ AppComponent ]
})
Después de eso, ahora puede usar su proveedor http personalizado en sus servicios. Por ejemplo:
user.service.ts
import { Injectable } from ''@angular/core'';
import {HttpService} from ''./http.service'';
@Injectable()
class UserService {
constructor (private http: HttpService) {}
// token will added automatically to get request header
getUser (id: number) {
return this.http.get(`/users/${id}`).map((res) => {
return res.json();
} );
}
}