如何在 rxjs 6 中将 switchMap-运算符与函数体链接起来



我有一个移动应用程序,用离子和角度构建,我想将其从rxjs 5.5升级到rxjs 6。但是,rxjs 使用运算符的方式似乎有一些重大变化,尤其是在管道链中的下一个运算符中处理一个 switchMap 运算符返回的值的方式。这在迁移文档 (https://rxjs-dev.firebaseapp.com/guide/v6/migration( 中不清楚,我找不到解决方法。

问题可能出在我在switchMap运算符中使用函数体。这种方法是基于较旧的互联网资源,但我在最近的例子中看到的较少,并且不确定它是否仍然应该使用。

我需要这种方法的原因是,我使用可观察量的方式或多或少是作为承诺的替代品 - 这是一种确保不同步骤按顺序运行的方法。因此,没有一个数据流通过运算符运行,但任何运算符都可能是新类型事件的开始。这是过去作出的决定,目的是防止可观察量和承诺之间不断转换。现在来看,这可能不是好的做法,但现在,如果可能的话,我宁愿保持原样。

无论如何,以以下内容为例:

initializeStatisticsObs(): Observable<any> {
return this.speciesService.getImagesSizeInBytesObs()
.pipe(
switchMap((fSizeInBytes: number) => {
this.imagesSizeInBytes = fSizeInBytes;
return this.speciesService.getImagesNumberOfItemsObs();
}),
switchMap((fNumberOfItems: number) => {
this.imagesNumberOfItems = fNumberOfItems;
return of({});
}),
..
)
}
getImagesSizeInBytesObs(): Observable<number> {
return this.speciesLocalStorageService.getSizeInBytesObs();
}
getImagesNumberOfItemsObs(): Observable<number> {
return this.speciesLocalStorageService.getNumberOfItemsObs();
}

如您所见,更高级别的函数 initializeStatisticsObs(( 调用另外两个函数,这两个函数都返回一个数字,包装在一个 Observable 中。这两个数字最终都应存储在 number 类型的变量中。我知道在这种情况下,异步运行的整个想法似乎没有意义,但它只是一个简化的示例。

因此,对this.speciesService.getImagesSizeInBytesObs((的调用是在管道链之外调用的,其输出在第一个switchMap中拾取,并存储在类型为number的变量中。

然后调用第二个类似的函数this.speciesService.getImagesNumberOfItemsObs((,该函数再次返回一个包装在Observable中的数字。第二个调用应由第二个 switchMap 运算符拾取,并再次存储在类型为 number 的变量中。

这种方法在 rxjs 5.5 中运行良好,但我在 6.4.0 或更高版本中遇到构建错误。问题是显然 switchMap-运算符现在添加了一个额外的 Observable 包装器,因此第二个 switchMap 获取一个类型为<Observable<number>>的值作为输入,与 this.imagesNumberOfItems 的数字类型冲突。

我得到的构建错误如下所示:

Argument of type 'OperatorFunction<number, Observable<{}>>' is not assignable to parameter of type
'OperatorFunction<Observable<number>, Observable<{}>>'. Type 'number' is not assignable to type
'Observable<number>'.

我认为使用函数体是问题的原因的原因是,当我使用它时:

initializeStatisticsObs(): Observable<any> {
return this.speciesService.getImagesSizeInBytesObs()
.pipe(
switchMap((fSizeInBytes: number) => of(23)),
switchMap((fNumberOfItems: number) => {
this.imagesNumberOfItems = fNumberOfItems;
return of({});
})
..
)
}

它工作正常。

顺便说一下,tap(( 运算符可以与函数体一起使用而不会出现这些问题,但它们不适合我的目的。 有没有办法解决这个问题?

switchMap((fSizeInBytes: number) => {
this.imagesSizeInBytes = fSizeInBytes;
return this.speciesService.getImagesNumberOfItemsObs();
})

switchMap 返回 Observable 和 getImagesNumbersOfItemsObs 返回 Observable,因此您的返回是可观察的>

您应该使用"点按此处">

tap((fSizeInBytes: number) => this.imagesSizeInBytes = fSizeInBytes)
switchMap(() => this.speciesService.getImagesNumberOfItemsObs())
tap((fNumberOfItems: number) => this.imagesNumberOfItems = fNumberOfItems))

但最好在这里使用 forkJoin 运算符,并期望您的值在订阅中作为数组

最新更新