如何在订阅前有条件地使用 Observables 做一些事情?
How to do something conditionally with Observables before subscribe?
我正在尝试实施执行以下步骤的解决方案:
- 使用
filter
检查条件是否有效。
- 检查
Ctrl
是否被按下,如果是则执行一些功能。
- 最后,再执行一个函数。
我能够使用该代码使其工作:
const click = Observable.fromEvent(element, 'click');
click.filter(() => condition)
.do((event: MouseEvent) => {
if (!event.ctrlKey) {
// maybe do something...
}
}).subscribe(() => {
// aways do something else at end
});
我想知道是否有更优雅的解决方案可以删除 do
方法中的 if 条件?
不确定我是否理解这个问题,但这里有一种类似的方法可以做到这一点并尽量保持代码整洁:
const click$ = Observable.fromEvent(document, 'click');
// I don't know what's in your condition so I just return true
const condition = () => true;
const fnCtrlIsPressed = () => 'Ctrl is pressed';
const fnCtrlIsNotPressed = () => 'Ctrl is not pressed';
click$
.map(event => event.ctrlKey)
.map(isCtrlPressed => isCtrlPressed ?
fnCtrlIsPressed():
fnCtrlIsNotPressed())
.do(console.log)
.subscribe();
输出将是这样的:
这是一个可用的 Plunkr:https://plnkr.co/edit/VwuXkk0QnVGC4hPCvtOo?p=preview
一个选项是使用一个流来 flatMap,在按下 Ctrl 键的情况下触发适当的操作,这与您的方法没有太大区别。
const condition = () => true;
const clickStreamWithCtrlAction = Observable.fromEvent(element, "click")
.flatMap(event => event.ctrlKey
? Observable.of(event).do(clickWithCtrl => console.log("With ctrl clause"))
: Observable.of(event)
)
clickStreamWithCtrlAction
.filter(condition)
.subscribe(event => console.log(`Finally clause, ctrlKey: ${event.ctrlKey}`));
为什么不使用管道方法。
是这样的:
import { Observable, tap, filter } from 'rxjs';
const click = Observable.fromEvent(element, 'click')
.pipe(filter((valueEmitted) => {
//your filter comes here. if everything ok return true;
}), tap((valueEmitted) => {
//do something before subscribe
}));
然后您可以订阅 click observable。
关于点击的更多详细信息:https://www.learnrxjs.io/learn-rxjs/operators/utility/do
有关过滤器的更多详细信息:https://www.learnrxjs.io/learn-rxjs/operators/filtering/filter
我正在尝试实施执行以下步骤的解决方案:
- 使用
filter
检查条件是否有效。 - 检查
Ctrl
是否被按下,如果是则执行一些功能。 - 最后,再执行一个函数。
我能够使用该代码使其工作:
const click = Observable.fromEvent(element, 'click');
click.filter(() => condition)
.do((event: MouseEvent) => {
if (!event.ctrlKey) {
// maybe do something...
}
}).subscribe(() => {
// aways do something else at end
});
我想知道是否有更优雅的解决方案可以删除 do
方法中的 if 条件?
不确定我是否理解这个问题,但这里有一种类似的方法可以做到这一点并尽量保持代码整洁:
const click$ = Observable.fromEvent(document, 'click');
// I don't know what's in your condition so I just return true
const condition = () => true;
const fnCtrlIsPressed = () => 'Ctrl is pressed';
const fnCtrlIsNotPressed = () => 'Ctrl is not pressed';
click$
.map(event => event.ctrlKey)
.map(isCtrlPressed => isCtrlPressed ?
fnCtrlIsPressed():
fnCtrlIsNotPressed())
.do(console.log)
.subscribe();
输出将是这样的:
这是一个可用的 Plunkr:https://plnkr.co/edit/VwuXkk0QnVGC4hPCvtOo?p=preview
一个选项是使用一个流来 flatMap,在按下 Ctrl 键的情况下触发适当的操作,这与您的方法没有太大区别。
const condition = () => true;
const clickStreamWithCtrlAction = Observable.fromEvent(element, "click")
.flatMap(event => event.ctrlKey
? Observable.of(event).do(clickWithCtrl => console.log("With ctrl clause"))
: Observable.of(event)
)
clickStreamWithCtrlAction
.filter(condition)
.subscribe(event => console.log(`Finally clause, ctrlKey: ${event.ctrlKey}`));
为什么不使用管道方法。 是这样的:
import { Observable, tap, filter } from 'rxjs';
const click = Observable.fromEvent(element, 'click')
.pipe(filter((valueEmitted) => {
//your filter comes here. if everything ok return true;
}), tap((valueEmitted) => {
//do something before subscribe
}));
然后您可以订阅 click observable。
关于点击的更多详细信息:https://www.learnrxjs.io/learn-rxjs/operators/utility/do
有关过滤器的更多详细信息:https://www.learnrxjs.io/learn-rxjs/operators/filtering/filter