在我的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;
}
}
);
}
}
错误
它应该做什么
我希望我的组件按此顺序执行功能。
我想执行getActiveProducts()
,以便我的productService
从api获取产品并存储它们。
我想执行getPriceLists()
productService
来从其他服务获取数据并将其存储在productService
中。
我想执行populatePriceListMap()
,以便填充不同的服务属性。
我想在我的组件中执行populatePrices()
并将值分配给不同的属性。
我正面临的问题
我认为它执行第1步和第4步,而第1步正在执行其工作。我想显示在步骤4中设置的属性,但它不会分配它们并给出错误。
答案 0 :(得分:0)
您已在订阅中的pricesMap
回调中设置此onNext
变量,然后在onCompleted
回调中访问该变量。
您显然将其设置为未定义的值,该值作为值传入。那是错误。
至于最佳做法,您可能希望了解如何执行Rx in an Rx-like way。
答案 1 :(得分:0)
如果你可以同时接听并行(一个呼叫不依赖于另一个,只需要同步结果),那么我建议使用forkJoin
运算符。它是处理并行调用的地方,它等待它们全部完成之后再为每个调用抽取结果。
例如: 编辑:之前有一个错误:我把第二个observable的take(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
});