2016-07-06 10 views
3

Für den Hinweis, ich bin ziemlich uninitiiert zu Angular (1 oder 2 für diese Angelegenheit).Injected Service ist undefiniert direkt im Konstruktor

Ich versuche eine "super" Schicht von Http zu schreiben, um zu vermeiden, überall die gleichen Überschriften zu setzen.

import {Http, ConnectionBackend, RequestOptions, Response, Headers} from '@angular/http'; 
import {Observable} from 'rxjs'; 
import {LoadingService} from "../../services/loading.service"; 

export class HttpLoading extends Http { 
    constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, 
     private _ls: LoadingService) 
    { 
     super(backend, defaultOptions); 
    } 

    getPostPutHeader() { 
     var authHeader = new Headers(); 
     authHeader.append("Authorization", "Bearer "+ localStorage.getItem('token')); 
     authHeader.append('Content-Type', 'application/json'); 
     return authHeader; 
    } 

    post(url: string, data:any):Observable<Response> { 
     this._ls.isLoading = true; // Exception here: this._ls is undefined 
     return super.post(url, data, { headers: this.getPostPutHeader() }) 
      .map(res => { 
       this._ls.isLoading = false; 
       return res; 
      }); 
    } 
} 

Und ein Dienst zu sagen, wenn eine Anfrage ausgeführt wird; Es ist in der obigen Klasse HttpLoading injiziert.

import {Injectable} from '@angular/core'; 

@Injectable() 
export class LoadingService { 
    isLoading: boolean = false; 
} 

ich ein paar Sachen in meinem Bootstrap, einschließlich HttpLoading, LoadingService und ConnectionBackend (für diese letzte, erhalte ich eine Ausnahme, wenn es nicht da ist).

bootstrap(AppComponent, [ 
    ConnectionBackend, 
    HttpLoading, 
    APP_ROUTER_PROVIDERS, 
    HTTP_PROVIDERS, 
    LoadingService, 
    disableDeprecatedForms(), 
    provideForms() 
]) 

Das Problem ist, dass das erste Mal, dass ich HttpLoading ‚s post Verfahren (in einem weiteren Dienst), ich eine Ausnahme bei this._ls.isLoading bekommen, weil this._ls nicht definiert ist, und ich kann nicht verstehen, warum.

Bitte sagen Sie mir, wenn Sie weitere Informationen benötigen.


bearbeiten

LoadingService ist in meinem AppComponent (Hauptbestandteil) korrekt injiziert.

//imports 
//@Component 
export class AppComponent { 
    requesting:boolean = false; 

    constructor(public authService: AuthService, private router: Router, private _ls: LoadingService) { 
    } 

    navigate(route:string) { 
     this._ls.isLoading = true; 
     this.router.navigate([route]) 
      .then(() => this._ls.isLoading = false); 
    } 
} 

Mögliche Lösung

Es scheint, dass Ihre öffentlichen/privaten Parameter müssen zuerst in der Liste platziert werden. Ich lasse jemand mehr qualifiziert als ich erklären, warum, obwohl ...

export class HttpLoading extends Http { 

    constructor(private _ls: LoadingService, backend: ConnectionBackend, defaultOptions: RequestOptions) { 
     super(backend, defaultOptions); 
} 

Antwort

2

Ich würde Ihre HttpLoading Klasse auf diese Weise in den Providern konfigurieren, wenn die Anwendung Bootstrapping:

bootstrap(AppComponent, [ 
    (...) 
    HTTP_PROVIDERS, 
    { 
    provide:Http, 
    useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, loadingService: LoadingService) => { 
     return new HttpLoading(backend, defaultOptions, loadingService); 
    }, 
    deps: [XHRBackend, RequestOptions, LoadingService] 
    } 
]); 

Den Grund für diesen ist, dass Sie Ihre eigene Klasse für den HTTP-Provider verwenden möchten. Sie müssen die Klasse hinter dem HTTP-Anbieter durch Ihre HttpLoading Klasse ändern. Achten Sie darauf, es nach HTTP_PROVIDERS zu definieren.

Um die Instanz von XHRBackend Ihre Klasse zu injizieren, müssen Sie useFactory verwenden ...

+0

Könnten Sie bitte erklären, warum, wenn das nicht zu viel Aufwand ist? Ich denke auch, dass Sie eine schließende geschweifte Klammer vermissen; Ich habe einen Fehler in meiner IDE – Kilazur

+0

Ich fügte einige Erklärungen in meiner Antwort hinzu ... Fühlen Sie sich frei, mir zu sagen, wenn es Ihre Frage beantwortet ... Sonst haben Sie Recht. Ein '{' musste entfernt werden ;-) Danke, dass du darauf hingewiesen hast! –

+0

Vielen Dank. Ich verstehe immer noch nicht alles, aber das ist ein Anfang! Ändert das automatisch Http mit HttpLoading, wenn ich Http in meinen Komponenten verwende? Und sollte ich ConnectionBackend durch XHRBackend im Konstruktor von HttpLoading ersetzen? – Kilazur

0

Ok, ich weiß, dass trivial erscheinen mag, aber versuchen, eine Variable zu erstellen und es im Konstruktor initialisieren

+0

Ich empfehle auch dies - die Optimierungs-Engine entfernt möglicherweise den Verweis auf diese Abhängigkeit. –

+1

Noch undefiniert. – Kilazur

+2

Außerdem sehe ich nicht, wie es funktionieren würde, das könnte keine Lösung auf irgendeiner Ebene sein. Ein in den Konstruktor injizierter Dienst sollte immer im zugrunde liegenden Kontext verfügbar sein. –

0

Um @Thierry Templiers Antwort zu erweitern. Ich benutze Angular v4, und meine Erfahrung ist, dass Sie alle Abhängigkeiten, die Ihr erweiterender Konstruktor benötigt, UND in der richtigen Reihenfolge bereitstellen müssen - ich denke, es ist eine traditionelle Art, es zu tun, von eckigen 1.x.

Mein Beispiel:

// Das ist meine erweiterten Klasse (relevanter Teil nur)

@Injectable() 
export class HttpService extends Http { 

    constructor(
     backend: ConnectionBackend, 
     defaultOptions: RequestOptions, 

     private router: Router, 
     private loaderService: LoaderService, 
     private modalService: ModalService, 
     private localStorageService: LocalStorageService 
    ) 
    { 
     super(backend, defaultOptions) 
    } 

// Dies ist der Anbieter Fabrik in app.module definiert.ts:

export function httpClientFactory(
     backend: XHRBackend, 
     defaultOptions: RequestOptions, 
     router: Router, 
     loaderService: LoaderService, 
     modalService: ModalService, 
     localStorageService: LocalStorageService 
    ) : Http 
{ 
    return new HttpService(
     backend, 
     defaultOptions, 
     router, 
     loaderService, 
     modalService, 
     localStorageService 
    ); 
} 

Dies ist die Konfiguration (nur den relevanten Teil links) in app.module.ts:

providers: [ 
    ModalService 
    LocalStorageService, 
    LoaderService, 
    { 
     provide: HttpService, 
     useFactory: httpClientFactory, 
     deps: [XHRBackend, RequestOptions, Router, LoaderService, ModalService, LocalStorageService] 
    } 

Hinweis: Beachten Sie die Reihenfolge der deps in der Config zu erklären im Vergleich zur Fabrik Konstruktor .. es ist das gleiche

Verwandte Themen