我有两种API方法:
POST
/ articles / {id} /修订GET
/ articles / {id} 发布到修订的结果是修订文档,其中包括对文章对象进行更改之前/之后。这不是文章对象。
这些对应于我的Angular应用程序中的以下方法:
this.endpoint.articles.revise(article.id, revisionParams);
this.endpoint.articles.getById(article.id);
分别返回Observable<ArticleRevision>
和Observable<Article>
。
当我修改文档时,我想提取具有更改的文档的更新副本。目前,我可以通过执行以下操作来实现此目标:
private reviseArticle(article: article, revisionParams: ArticleRevisionParams): Observable<Article> {
return this.endpoint.articles.revise(article.id, revisionParams)
.expand(r => this.endpoint.articles.getById(article.id))
.pipe(take(2))
.last();
}
从描述或expand
看来,此方法更像是一种技巧,而不是解决方案:
递归调用提供的函数。
我尝试使用concat
,但发现它需要使用相同类型的可观察对象,在我的情况下,这有点令人不快。我是在滥用expand
,还是有一种更好的(更正确的)方式来顺序链接不同的可观察对象?
P.S。我标记了Angular,以防rxjs的Angular捆绑风格与常规rxjs略有不同。如果不属于它,请随时将其删除。
答案 0 :(得分:2)
要在不使用容器类型的情况下完成此操作,可以利用forkJoin
运算符。
这个想法是构成中间结果,以便它由您的第一个请求的结果以及第二个请求的结果(取决于您的第一个请求)组成。此组合的一部分要求您将第一个请求结果转换为可观察的结果,您可以使用of
进行此操作。
随后,您可以从单个结果数组参数(即([reviseResult, getByIdResult]) => { ... }
)解构每个请求的响应。
const { forkJoin, of } = rxjs;
const { switchMap } = rxjs.operators;
function revise(id, params) {
return of({ id, params, operation: 'revise' });
}
function getById(id) {
return of({ id, operation: 'getById' });
}
revise(1).pipe(
switchMap(reviseResult => forkJoin(of(reviseResult), getById(reviseResult.id))),
).subscribe(console.log);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script>
答案 1 :(得分:1)
出于记录,我相信Angular会基于this package.json使用与我们其他人相同的rxjs库。
幸运的是,rxjs提供了许多以不同方式完成任务的选项。我个人还没有以这种方式使用扩展,但是它看起来像是一个非常简洁的实现。
执行此操作的一种方法是创建一个新接口来容纳这两种类型:
export interface MyTypes {
rev: ArticleRevision;
article: Article;
}
通过这种方式,您可以使用switchMap operator从流中返回一种类型,并在一种类型上设置两个响应的值并返回可观察值。
草稿
export interface MyTypes {
rev: ArticleRevision;
article: Article;
}
private reviseArticle(article: article, revisionParams: ArticleRevisionParams): Observable<MyTypes> =>
this.endpoint.articles.revise(article.id, revisionParams)
.pipe(
switchMap((rev: ArticleRevision) =>
this.endpoint.articles.getById(article.id)
.pipe(
switchMap((art: Article) => ({
rev: rev,
article: art,
})
)
);
您还可以使用switchMap以可观察的方式返回两个值的数组(类似于上面的内容,只需将它们返回到数组中即可)。