2016-12-08 65 views
0

在我的angular2應用程序中,我想按順序執行可觀察訂閱,但由於第一次訂閱有一個我認爲需要大量時間的方法而出現錯誤。我爲不同的組件提供服務,以便他們緩存我的數據並可供所有組件使用。我是Http Observables新手,不知道它們執行的順序。如何推遲可觀察訂閱,從第一個可觀察到的完成方法執行

PriceList.service.ts

export class PriceListService 
{ 
    private priceLists : PriceList[]; 
    private observable : Observable<any>; 
    public getAll() 
    { 
     if(this.priceLists) 
     { 
      return Observable.of(this.priceLists); 
     } 
     else if (this.observable) 
     { 
      return this.observable; 
     } 
     else 
     { 
      this.observable = this.authHttp.get(this.appService.getApiUrl() + "api/price-list/list") 
       .map(response => { 
        this.observable = null; 
        if(response.status == 400) 
        { 
         return "Failure"; 
        } 
        else if(response.status == 200) 
        { 
         let myJson = response.json(); 
         this.priceLists = myJson.data.priceList; 
         return this.priceLists; 
        } 
       }) 
       .share(); 
      return this.observable; 
     } 
    } 
} 

Product.service.ts

export class ProductService 
{ 
    products : Product[]; 
    observable : Observable<any>; 
    priceLists : any; 
    priceListMap : Map<number, any> = new Map<number, any>(); 
    defaultPriceList : Map<number, any> = new Map<number, any>(); 
    productMap : Map<number , any> = new Map<number , any>(); 
    defaultPriceListId : number; 
    public getActiveProducts() 
    { 
     if(this.products) 
     { 
      return Observable.of(this.products); 
     } 
     else if (this.observable) 
     { 
      return this.observable; 
     } 
     else 
     { 
      this.observable = this.authHttp.get(this.appService.getApiUrl() + "api/product/list/active") 
       .map(response => { 
        this.observable = null; 
        if(response.status == 400) 
        { 
         return "Failure"; 
        } 
        else if(response.status == 200) 
        { 
         let myJson = response.json(); 
         this.products = myJson.data.products; 
         this.getPriceLists(); 
         return this.products; 
        } 
       }) 
       .share(); 
      return this.observable; 
     } 
    } 
    getPriceLists() 
    { 
     this.priceListService.getAll().subscribe(
      success => { this.priceLists = success; }, 
      error => {}, 
      ()=> { this.populatePriceListMap(); } 
     ); 
    } 
    populatePriceListMap() 
    { 
     for(let priceList of this.priceLists) 
     { 
      for(let product of this.products) 
      { 
       for(let prices of product.prices) 
       { 
        if(priceList.id == prices.priceList.id) 
        { 
         this.productMap.set(product.id , {price : prices.price , discount : prices.discount}); 
        } 
       } 
      } 
      if(priceList.isDefault == 1) 
      { 
       this.defaultPriceList.set(priceList.id , this.productMap); 
       this.defaultPriceListId = priceList.id; 
      } 
      this.priceListMap.set(priceList.id , this.productMap); 
      this.productMap = new Map<number , any>(); 
     } 
    } 
    getDefaultList() 
    { 
     if(this.defaultPriceList){ 
      return Observable.of(this.defaultPriceList.get(this.defaultPriceListId)); 
     } 
    } 
} 

ListProduct.component.ts

export class ListProductsComponent implements OnInit 
{ 
    products:any = null; 
    pricesMap : Map<number, any> = new Map<number, any>(); 
    prices:any = []; 
    discounts:any = []; 
    ngOnInit() 
    { 
     this.productService.getActiveProducts().subscribe(
      success =>{ 
       this.products = success; 
      }, 
      error =>{}, 
      () =>{ 
       this.populatePrices(); 
      } 
     ); 
    } 
    populatePrices() 
    { 
     this.productService.getDefaultList().subscribe(
      success => 
      { 
       this.pricesMap = success; 
      }, 
      error =>{}, 
      ()=>{ 
       for (let product of this.products) 
       { 
        let myObject = this.pricesMap.get(product.id); 
        this.prices[product.id] = myObject.price; 
        this.discounts[product.id] = myObject.discount; 
       } 
      } 
     ); 
    } 
} 

錯誤

error

它應該做的

我希望我的組件順序執行的功能。

  1. 我想執行getActiveProducts()讓我productService獲取來自API,並將其存儲產品。

  2. 我想執行getPriceLists()productService從其他服務獲取數據並將其存儲在productService中。

  3. 我想執行populatePriceListMap(),以便它填充服務的不同屬性。

  4. 我想在我的組件中執行populatePrices()並將值分配給不同的屬性。

問題我現在面臨

我想它,而第1步是做其工作執行步驟1和4。我想要顯示在步驟4中設置的屬性,但它不分配它們並給出錯誤。

回答

0

您正在設置pricesMap變量onNext回調中的訂閱,然後在onCompleted回調中訪問它。 你很明顯將它設置爲一個未定義的值作爲值。這是錯誤。

至於最佳做法,你可能想看看如何做Rx,in an Rx-like way

0

如果您可以同時撥打電話(一個通話不依賴另一個,只需要同步結果),那麼我會建議使用forkJoin運營商。它處理並行調用,等待它們全部完成,然後再抽取每個結果。

例如: 編輯:有一個錯誤之前我把取(2)第二個觀察的時候應該也已經採取(1)

var obs1 = this.authHttp.get(firstUrl).take(1); 
var obs2 = this.authHttp.get(secondUrl).take(1); 
Observable.forkJoin(obs1, obs2) 
      .subscribe(responseArray => { 
       // Do something 
       // where responseArray[0] is the response you receive from the first get call, obs1 
       // responseArray[1] is the response you receive from the second get call, obs2 
      }); 

你可以閱讀更多關於在這裏:https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/forkjoin.md

但是,如果你想運行它們順序(第二get調用需要從第一個GET的響應參數),那麼你正在尋找的switchMap操作。因此,使用上述相同的obs1和obs2,您需要執行以下操作:

obs1.do(resp1 => { 
     // Anything you want to do with the first response before you fire off the second one 
    }).switchMap(obs2) 
    .subscribe(resp2 => { 
       // Do something 
    });