2016-12-08 49 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 
    });