在管道内使用 concatMap 两次的更好替代方案?
我想在另一个承诺(承诺 1)解析后递归执行一个预定义的承诺(承诺 2),以查看我与外围设备的连接何时返回 false,然后我可以执行其他操作。我希望能够使用可观察量来做到这一点。这是我到目前为止编写的代码,有两个问题:
1)是否有更好的替代方案可以在 reprovision() 函数中的代码中使用 concatMap 两次 ,
以及
2)是否有更好的方法来实现我的代码来执行我上面描述的操作?
下面是使用 observables 递归执行 Promise 1(仅一次)和 Promise 2,然后对结果执行某些操作的代码:
reprovision(){
this.bleMessage = this.prepareMessageService.prepareMessage(
MessageCategory.customAction, CustomActionConstants.reboot, this.customPayload
);
from(this.bleService.bleWrite('custom', this.bleMessage)).pipe(
concatMap(x => interval(1000)),
concatMap(x => this.bleService.checkBleConnection1(this.deviceId)),
takeWhile(x => x, true)).subscribe(
resp => console.log('still connected to peripheral'),
err => {
console.log('disconnected from peripheral, do something else');
}
);
}
这是 Promise 2 (this.bleService.checkBleConnection1) 的代码,我希望递归执行它,直到外围设备断开连接从我的移动设备。这个承诺背后的想法是,只要我的移动设备仍然连接到外围设备,它就应该解决,并在连接失败时抛出错误。
checkBleConnection1(deviceId: string){
return BleClient.getConnectedDevices([]) //BleClient.getConnectedDevices([]) returns a promise
.then(resp => {
if (!resp.some(elem => deviceId === elem.deviceId)){
throw new Error('Peripheral connection failed');
}
return true;
})
.catch(error => {
throw error;
});
}
I want to execute a pre-defined promise (promise 2) recursively after another promise (promise 1) resolves to see when my connection to a peripheral device returns false, following which I can do something else. I'd like to be able to do so using observables. Here's the code I've come up with so far and have 2 questions:
1) Is there a better alternative to using concatMap twice in my code in the reprovision() function,
and
2) Is there a better way to implement my code to do what I've described above?
Here's the code which uses observables to execute promise 1 (only once) and promise 2 recursively and then does something with the result:
reprovision(){
this.bleMessage = this.prepareMessageService.prepareMessage(
MessageCategory.customAction, CustomActionConstants.reboot, this.customPayload
);
from(this.bleService.bleWrite('custom', this.bleMessage)).pipe(
concatMap(x => interval(1000)),
concatMap(x => this.bleService.checkBleConnection1(this.deviceId)),
takeWhile(x => x, true)).subscribe(
resp => console.log('still connected to peripheral'),
err => {
console.log('disconnected from peripheral, do something else');
}
);
}
Here's the code for promise 2 (this.bleService.checkBleConnection1), which I want executed recursively until the peripheral is disconnected from my mobile device. The idea behind this promise is that it should resolve as long as my mobile device is still connected to a peripheral, and throw an error once that connection fails.
checkBleConnection1(deviceId: string){
return BleClient.getConnectedDevices([]) //BleClient.getConnectedDevices([]) returns a promise
.then(resp => {
if (!resp.some(elem => deviceId === elem.deviceId)){
throw new Error('Peripheral connection failed');
}
return true;
})
.catch(error => {
throw error;
});
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
从您的帖子中我了解到,
this.bleService.checkBleConnection1(this.deviceId)
以 1 秒的间隔进行递归检查因此,对于递归调用,Rxjs 中有一个名为
expand
链接要实现 1 秒间隔添加
delay(1000) 在返回递归调用时
所以这是我的版本,使用
expand
代替concatMap(x =>; Interval(1000))
使用
expand
不需要使用takeWhile
,所以我将其删除From your post what I understood is
this.bleService.checkBleConnection1(this.deviceId)
infinitely if device is foundSo for recursive call there is an operator in Rxjs called
expand
linkTo achieve 1 sec interval adding
delay(1000)
while returning for recursive callSO here is my version using
expand
in place ofconcatMap(x => interval(1000))
using
expand
there is no need of usingtakeWhile
,so am removing it我相信这里的目标是在完成第一个承诺后每 1 秒检查一次连接(旁注:这称为轮询,而不是递归,如果您调用
reprovision()
从内部reprovision()
或类似的东西,您可以递归轮询,但您不在这里并且通常不想这样做,除非必须这样做)。你不能真正摆脱第二个
concatMap
因为你必须根据时间间隔切换到它,你可以像这样分离和清理流:但你需要小心使用像 concatMap 这样的运算符,因为它会产生背压,这对应用程序不利。如果这些请求的响应时间可能超过 1 秒,那么您将构建一个请求队列,这可能会降低应用程序的性能。更安全的替代方案是
switchMap
和exhaustMap
,具体取决于所需的行为I believe the goal here is to check the connection every 1 second after you've completed the first promise (side note: this is called polling, not recursion, it'd be recursive if you called
reprovision()
from insidereprovision()
or something similar, you can poll recursively but you're not here and generally don't want to unless you have to).You can't really get rid of the second
concatMap
because you have to switch into it based on the interval, you can separate and clean up the streams a little bit like this:but you need to be careful with an operator like
concatMap
as it can build backpressure which is bad for an app. if these requests can take longer than 1 second to respond, then you'll be building a queue of requests which can deteriorate your application performance. safer alternatives areswitchMap
andexhaustMap
depending on desired behavior