在 RxJS 6 管道中使用 forkJoin 作为可出租运算符

Using forkJoin as lettable operator in RxJS 6 pipe

最终目标
我有一个 user/device 注册方法。在其中我需要:

  1. 检查本地存储是否就绪
  2. 如果是,请分别检查 deviceId 和 token
  3. 如果没有找到 deviceId 或 token,调用注册端点

我在哪里
在构建过程中,为了简单起见,我没有处理令牌化。我只使用 deviceId 和下面的 worked/works 非常好。

我调用我的 isStorageReady 帮助程序方法,检查响应,然后调用我的 getDeviceId 帮助程序方法,并检查该响应。

this.isStorageReadyAsync()
    .pipe(
        map(storageResponse => {
            // check storageResponse
            // if undefined throw error
            // error picked up by retryPipeline
            // if retryPipeline exhausted picked up 
            // by errorPipeline and stream is stopped
            if (storageRes === undefined ||
                storageRes['LOCALSTORAGE'] === undefined ||
                storageRes['LOCALSTORAGE'] === '') throw 'storageRes or 
                storageRes.LOCALSTORAGE are undefined or empty';
        }),
        flatMap(_ => this.getStoredDeviceIdAsync()),
        map(deviceId => {
            return iif(() => deviceId === undefined || 
                             deviceId === null || 
                             deviceId === '',
                       // no deviceId stored on device
                       // register device to get deviceId
                       this.registerDeviceAsync(), 
                       // deviceId found in local storage
                       of({id: deviceId, new: false}))
        }),
        this.storeDeviceIdPipeline, // store deviceId
        this.retryPipeline, // retry if e.g. experiencing network issues
        this.errorPipeline // catch and handle errors
    )

我被困在哪里
我有第二个辅助方法 getStoredTokenAsync(),我想将其与 getStoredDeviceIdAsync() 并行调用。我试过使用 forkJoin 并将数组传递给后面的 map 运算符,但我的打字稿 linter 根本不喜欢这样。 forkJoin 之前的所有内容都带有下划线,就好像这是一个错误,错误内容如下:

Argument of type OperatorFunction is not assignable to parameter of type OperatorFunction. Type void is not assignable to type {}.

所以我不太明白。我希望使用这样的东西:

...
forkJoin([this.getStoredDeviceIdAsync(), this.getStoredTokenAsync()]),
map(authArr => {
   let deviceId = authArr[0];
   let token = authArr[1];
   ...
})
...

感谢两位评论者 LookForAngular 和 Julius Dzidzevičius 帮助整理这些内容!如果这对其他人有帮助,我会在这里提供完整的答案。还为一些额外的上下文提供更多代码。

mergeMapTo 调用之前,有一些通用的响应检查。它的输出不会被消耗,所以使用 mergeMapTo 是合适的(意味着它之前发生的任何事情都与 mergeMapTo 内部发生的事情无关)。

mergeMap 本质上使内部可观察对象变平,这是由我的 iif 调用提供的。 mergeMap 的输出被路由到我的存储管道(这只是一个 map 调用),它处理与用户身份验证等相关的所有逻辑。

pipe(
    ...
    mergeMapTo(forkJoin([this.getStoredDeviceIdAsync(), this.getStoredTokenAsync()])),
    mergeMap(authArr => {
        let deviceId = authArr[0];
        let token = authArr[1];
        return iif(() => deviceId === undefined || deviceId === null || deviceId === '' ||
                         token === undefined || token === null || token === '',
                         this.registerDeviceAsync(), // register device to get deviceId and token
                         of({deviceId: deviceId, token: token, new: false})) 
    }),
    this.storeDeviceIdTokenPipeline,
    this._config.retryPipeline, // generic retryWhen procedure
    this._config.errorPipeline // generic catchError procedure
)