2016-08-01 10 views
1

Ich habe einen Dienst, der Informationen vom Server anfordert. Ich muss die Anfrage nur einmal ausführen und für jede Komponente verfügbar machen. Bisher habe ich:Angular2 Service läuft http-Methode nur einmal

@Injectable() 
export class ProductService { 
    private products: Observable<IProduct[]>; 
    private _productUrl = 'app/api/products2.json'; 

    constructor(private _http: Http) { 
     console.log(this.products); 
     this.products = this.setProducts(); 
    } 

    setProducts(): Observable<IProduct[]> { 
     return this._http.get(this._productUrl) 
      .map((response: Response) => <IProduct[]>response.json()) 
      .do(data => console.log('A: ' + JSON.stringify(data))) 
      .catch(this.handleError); 
    } 

    getProducts(): Observable<IProduct[]> { 
     return this.products; 
    } 

    private handleError(error: Response) { 
     return Observable.throw(error.json().error || 'Server error'); 
    } 
} 

Wenn die Route ändert, ist es den Konstruktor setProducts Linie wieder läuft. this.products ist immer undefiniert, wenn es protokolliert wird, so dass eine if-Anweisung nicht funktioniert. Was kann ich ändern, um sicherzustellen, dass diese HTTP-Anfrage nicht ausgeführt wird, wenn der Dienst diese Informationen bereits haben sollte?

Danke!

+0

Siehe auch http://stackoverflow.com/questions/36271899/what-is-the-correct-way-to-share-the-result-of-an-angular-2- http-network-call-in –

Antwort

1

tun dies in der Bootstrap

es, weil jedes Mal, ist eine neue Instanz des Dienstes für jeden Komponente erstellt wird

import {ProductService } from './app/services/product.service'; //put your path not mine 
import { provide } from '@angular/core'; 
import {ReflectiveInjector} from '@angular/core'; 

let injector = ReflectiveInjector.resolveAndCreate(HTTP_PROVIDERS); 
let http = injector.get(Http); 
let prodService = new ProductService (http);  

bootstrap(AppComponent, [ 
    [provide(ProductService ,{useValue:prodService})] 
]).catch(err => console.error(err)); 
0

eine private Eigenschaft Erstellen Sie das Ergebnis zwischenzuspeichern. Die erste Komponente, die Ihren Dienst verwendet, löst eine Serveranfrage aus, aber die nachfolgenden Anfragen erhalten die zwischengespeicherten Produkte.

@Injectable() 
export class ProductService { 
    private _productUrl = 'app/api/products2.json'; 
    private products: IProduct[]; 

    constructor(private _http: Http) {} 

    getProducts(): Observable<IProduct[]> { 
     if (this.products) { 
      return Observable.of(this.products); 
     } else { 
      return this._http.get(this._productUrl) 
      .map((response: Response) => <IProduct[]>response.json()) 
      .do(data => console.log('A: ' + JSON.stringify(data))) 
      .catch(this.handleError); 
     } 
    } 

    private handleError(error: Response) { 
     return Observable.throw(error.json().error || 'Server error'); 
    } 
} 
+0

Ich habe Ihren Code oben versucht und es funktionierte genauso wie der vorherige Code. Wo speichern Sie das Ergebnis? –

+0

Der obige Code funktioniert, hängt jedoch davon ab, wo Sie Ihren Dienst definieren. Es empfiehlt sich, diese Dienste den App-Komponentenanbietern hinzuzufügen, damit sie während der Ausführung Ihrer App aktiv sind und alle Routen das zwischengespeicherte Ergebnis abrufen. Überprüfen Sie, ob Sie die Dienste im App-Komponentenanbieter hinzugefügt haben. Ich speichere die Ergebnisse in der Produktvariablen. –

+0

Warum negativ? Bitte geben Sie eine Rückmeldung statt nur -1. –

0

Ok so @rashfmnb Sie waren auf der richtigen Linie. Ich musste es booten, und ich musste es als Konstruktor in meinen Kindkomponenten und nicht als Provider hinzufügen. Ich habe neue Instanzen davon erstellt.

Bootstrap: bootstrap(AppComponent, [HTTP_PROVIDERS, provideRouter(AppRoutes), [ProductService, otherService, anotherService, etc.]