Javascript RxJS:将对象键映射到可观察对象
我有一个向用户显示问题的应用程序。 问题草稿从SharePoint列表中加载。每个草稿都包含一个键,用于从另一个SharePoint列表加载对问题的正确回答。下面是我目前如何实现它的:Javascript RxJS:将对象键映射到可观察对象,javascript,typescript,rxjs,observable,Javascript,Typescript,Rxjs,Observable,我有一个向用户显示问题的应用程序。 问题草稿从SharePoint列表中加载。每个草稿都包含一个键,用于从另一个SharePoint列表加载对问题的正确回答。下面是我目前如何实现它的: interface QuestionDraft { title: string; responseKey: string; } interface Question { title: string; responses: string[]; } const drafts: QuestionDr
interface QuestionDraft {
title: string;
responseKey: string;
}
interface Question {
title: string;
responses: string[];
}
const drafts: QuestionDraft[] = [];
const questions: Question[] = [];
// stub
private getDrafts(): Observable<QuestionDraft> {
return from(drafts);
}
// stub
private getResponses(key: string): Observable<string> {
return of(key, key, key);
}
main(): void {
getDrafts().subscribe(
data => {
const res: string[] = [];
getResponses(data.responseKey).subscribe(
d => res.push(d),
error => console.error(error),
() => questions.push({
title: data.title,
responses: res
})
);
}, error => console.error(error),
() => console.log(questions)
);
}
接口问题草稿{
标题:字符串;
响应键:字符串;
}
接口问题{
标题:字符串;
答复:字符串[];
}
常量草稿:问题草稿[]=[];
常量问题:问题[]=[];
//存根
私有getDrafts():可观察{
退票(汇票);
}
//存根
私有getResponses(键:字符串):可观察{
返回(键,键,键);
}
main():void{
getDrafts()。订阅(
数据=>{
常量res:string[]=[];
getResponses(data.responseKey).订阅(
d=>res.push(d),
error=>console.error(错误),
()=>questions.push({
标题:data.title,
答复:res
})
);
},error=>console.error(错误),
()=>console.log(问题)
);
}
此解决方案工作正常,但我认为
main()
中的代码看起来很凌乱。有没有更简单的方法来做同样的事情,例如使用mergeMap
或类似的东西?您可以尝试使用flatMap
使它更干净。
如果您使用RxJS版本6,则必须使用pipe()方法并将flatMap转换为mergeMap 在rxjs 6中,@emcee22的示例如下:
this.getDrafts()
.pipe(
.mergeMap(function(x){return functionReturningObservableOrPromise(x)}),
.mergeMap(...ad infinitum)
).subscribe(...final processing)
您可以使用
mergeMap
映射到新的可观察对象,并使用toArray
收集阵列中发出的值。使用catchError
处理流中的错误,并映射到其他可观察到的错误
此代码的工作方式与您的代码相同,它包含所有问题,直到getDrafts
抛出错误,并排除getResponses
抛出错误的问题
getDrafts().pipe(
mergeMap(draft => getResponses(draft.responseKey).pipe(
toArray(),
map(responses => ({ title: draft.title, responses } as Question)),
catchError(error => { console.error(error); return EMPTY; })
)),
catchError(error => { console.error(error); return EMPTY; }),
toArray()
).subscribe(qs => { console.log(qs); questions = qs; })
请记住,最后一个数组中的问题
的顺序不一定与进入的草稿
的顺序相同。顺序取决于getResponses
Observable完成特定draft
的速度。(这与当前代码的行为相同)
为确保问题
的顺序与草稿
的顺序相同,您可以使用concatMap
而不是mergeMap
。但这可能会减慢任务的整体执行,因为下一个草稿
的响应将仅在上一个草稿
的响应完成后获取
getDrafts().pipe(
mergeMap(draft => getResponses(draft.responseKey).pipe(
toArray(),
map(responses => ({ title: draft.title, responses } as Question)),
catchError(error => { console.error(error); return EMPTY; })
)),
catchError(error => { console.error(error); return EMPTY; }),
toArray()
).subscribe(qs => { console.log(qs); questions = qs; })