我在一个应用程序中显示有关'Modyules'(在课程中)必须通过两个http.gets(我不能控制apis不幸)的信息:通过在ng2中的可观察对象的依赖和并行请求
- 获取Modyule.ids列表 - 需要存储的ID
- 对于每个Modyule.id另一个http.get得到Modyule.name
在我modyule.component.ts ,我有:
this.modyuleService.getModyules()
.subscribe(
modyules => this.modyules = modyules,
error => this.errorMessage = <any>error
);
在我modyule.service.ts,我有:
getModyules(): Observable<Modyule[]> {
return this.http.get(listOfModyuleIdsUrl + '.json')
.map(this.getModyulesDetails)
.catch(this.handleError);
}
但getModyuleDetails是我很努力。这是我有这么远,主要是基于:
http://www.syntaxsuccess.com/viewarticle/angular-2.0-and-http
,看着,但没有看到我如何申请:
https://stackoverflow.com/a/35676917/2235210
private getModyulesDetails = (res: Response) => { // instance method for defining function so that the this.http below refers to the class.
let listOfModyules = res.json();
let modyulesToReturn = [];
for (let individualModyule of listOfModyules){
let tempModyule = new Modyule;
tempModyule.id = individualModyule.id;
this.http.get(individualModyuleUrl + individualModyule.id + '.json')
.map((res: Response) => res.json()))
.subscribe(res => {
tempModyule.name = res.name
modyulesToReturn.push(tempModyule);
});
}
return modyulesToReturn;
}
现在,这是在我的本地机器上工作,在那里我将.json响应作为静态.json文件来模拟。但是,当我处理真正的api时,我无法依赖for循环中的http.gets完成在返回modyulesToReturn之前。
我已经在forkJoin上做了几次尝试,但没有看到如何将它与需要从第一个http.get捕获Modyule.id的要求结合起来。
我非常感谢任何有关如何执行并行请求的指针,这些请求依赖于初始请求,但能够将来自两者的数据组合起来。
编辑在向效应初探讨论,@马特和@batesiiic:
因此,在@ batesiiic的建议getModyulesDetails的重写拿起返回一个主题,我不能让我的头周围的问题是如何填充在Modyule.id在第一个呼叫,然后Modyule.name在第二次调用(不返回任何Modyule.id参考),即:
private getModyulesDetails = (res: Response) => { // instance method for defining function so that the this.http below refers to the class.
let listOfModyules = res.json();
let modyulesToReturn = [];
let calls = [];
for (let individualModyule of listOfModyules){
/* I REALLY NEED TO POPULATE Modyule.id HERE */
calls.push(
this.http.get(individualModyuleUrl + individualModyule.id + '.json')
.map((res: Response) => res.json()))
);
}
var subject = new Subject<Modyules[]>();
Observable.zip.apply(null, calls).subscribe((modyules: Modyules[]) => {
var modyulesToReturn = [];
modyules.forEach(modyule => {
let tempModyule = new Modyule;
/*I COULD POPULATE Modyle.name HERE BUT IT WON'T MATCH THE Modyule.id SET ABOVE - EXCEPT BY LUCK*/
modyulesToReturn.push(tempModyule);
}
subject.next(modyulesToReturn);
});
return subject;
}
我想我需要打的电话一个通过for循环中的一个,但以某种方式等待,直到他们已经回应modyulesToReturn之前所有响应?
感谢@马特。我可能会误解,但这不是我通过在地图回调(在服务中)中调用getModyulesDetails中的细节来收集有效信息吗?我仍然不确定如何让getModyule等到getModyuleDetails(即使插入的地方你提出作为一个服务方法,它自己的订阅回调)已经返回...做一个.subscribe回调,其中包含另一个.subscribe回调有等到第二次订阅被调用? – theotherdy
谢谢@Matt。你的解释非常清楚。 batesiiic +例如http://stackoverflow.com/a/38156976/2235210建议使用Rx.Subjects,但我真的不明白这是如何工作的。我是否正确地阅读你所说的,因为我应该避免单个组件中的这些依赖/链接请求,而是创建例如观察Observable getModyulesDetails方法的ModyuleDetailComponent?在这种情况下,我该如何让ModyuleDetailComponent知道ModyuleComponent已经完成获取Modyule.ids的列表,以便我可以例如@Input()他们到ModyuleDetailComponent? – theotherdy
这取决于。 batesiiic的方法是将所有东西都捆绑在一起,这样Subject/Observable就会触发一次。如果你订阅它,你会得到完整的细节清单。另一种方法是每当你从服务器得到响应时,将细节发送给你的组件。然后Subject/Observable会多次激发。如果你有大量的modyule,并且你宁愿向用户展示前10个,而不是让他等到所有1000个已经加载(比方说),那么这会很有用。 - batesiiic的代码提供了实现这两种方法的想法。 – Matt