2016-08-01 3 views
1

У меня есть служба, которая запрашивает информацию с сервера. Мне нужно только один раз запустить запрос и сделать его доступным для каждого компонента. До сих пор у меня есть:Angular2 Service работает http-метод только один раз

@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'); 
    } 
} 

При изменении маршрута, он запускает линию конструктор setProducts снова. this.products всегда не определено, когда оно регистрируется, поэтому выполнение инструкции if не работает. Что я могу изменить, чтобы убедиться, что этот HTTP-запрос не запущен, когда служба уже должна иметь эту информацию?

Спасибо!

+0

Смотрите также http://stackoverflow.com/questions/36271899/what-is-the-correct-way-to-share-the-result-of-an-angular-2- http-network-call-in –

ответ

1

сделать это в загрузчике

это потому, что каждый раз, когда новый экземпляр службы создается для каждого компонента

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

Создать частную собственность для кэширования результата. Первый компонент, использующий вашу службу, будет запускать запросы сервера, но последующие запросы получат кешированные продукты.

@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

Я пробовал ваш код выше, и он работал так же, как и предыдущий код. Где вы кешируете результат? –

+0

Приведенный выше код работает, но зависит от того, где вы определяете свой сервис. Это хорошая идея добавить эти сервисы к поставщикам компонентов приложения, поэтому он будет работать, пока ваше приложение будет запущено, и все маршруты будут извлекать результат кэширования. Проверьте, добавлены ли вы в поставщик компонентов приложения. Я кэширую результаты в переменной продуктов. –

+0

Почему отрицательный? Пожалуйста, дайте обратную связь, а не только -1. –

0

Хорошо, поэтому @rashfmnb вы были по правильной линии. Мне нужно было загрузить его, и мне нужно было добавить его как конструктор в мои дочерние компоненты, а не в качестве поставщика. Я создавал новые экземпляры.

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

Смежные вопросы