我需要将多个http调用的结果合并为一个Observable。调用必须按顺序进行,每个调用都必须等待上一个调用结束,并且直到运行时才知道http调用的数量。
我见过类似的问题,但是初始调用的数目一直是已知的,因此,几个嵌套和/或链接的管道操作可以轻松地解决这个问题。我将需要进行0到* API调用。
我认为 concatMap()
是必经之路,但我可能是错的。而且我不知道使它起作用的语法。
// Post all phones to API individually, but return updated results in single array.
savePhones(phones: Phone[]): Observable<Phone[]> {
let updatedPhones: Phone[] = [];
if (phones.length === 0) {
return of<Phone[]>(updatedPhones);
}
// I need to do something like this, but for 1 to **many** phones.
// When each Observable completes, add to array.
// Only after the prior Observable completes, start the next.
// When the last one is done, return the Observable array.
return this.postPhone(contactId, phones[0])
.pipe(
map(response1 => {
let p1 = new Phone();
p1.loadFromJson(response1);
updatedPhones.push(p1);
}),
concatMap(() => this.postPhone(contactId, phones[1])
.pipe(map(response2 => {
let p2 = new Phone();
p2.loadFromJson(response2);
updatedPhones.push(p2);
}))),
concatMap(() => this.postPhone(contactId, phones[2])
.pipe(map(response3 => {
let p3 = new Phone();
p3.loadFromJson(response3);
updatedPhones.push(p3);
}))),
map(() => {
return updatedPhones;
})
);
}
private postPhone(
contactId: string,
phone: Phone): Observable<Phone> {
let criteria = phone.toJson();
let url = phone.isNew()
? `${apiUrl}/contacts/${contactId}/phones/add`
: `${apiUrl}/contacts/${contactId}/phones/${phone.phoneId}/update`;
return this.httpClient.post(url, criteria));
}
谢谢。
答案 0 :(得分:0)
尝试forkJoin
savePhones(phones: Phone[]): Observable<Phone[]> {
return phones.length === 0 ? of<Phone[]>([]) : forkJoin(phones.map(
phone => this.postPhone(contactId, phone).pipe(
map(response => new Phone().loadFromJson(response)),
)
));
}