在 RxJS 6 管道中使用 forkJoin 作为可出租运算符
Using forkJoin as lettable operator in RxJS 6 pipe
最终目标
我有一个 user/device 注册方法。在其中我需要:
- 检查本地存储是否就绪
- 如果是,请分别检查 deviceId 和 token
- 如果没有找到 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
)
最终目标
我有一个 user/device 注册方法。在其中我需要:
- 检查本地存储是否就绪
- 如果是,请分别检查 deviceId 和 token
- 如果没有找到 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
)