这里是反应式编程的新手。
我正在尝试使用 ReactFX 在 JavaFX 中实现“惰性”实时搜索文本区域。这里的懒惰是指一旦用户停止输入一秒钟,它就会执行搜索。代码非常简单:
EventStream<Change<String>> textEvents = EventStreams.changesOf(textArea.textProperty())
.successionEnds(Duration.ofSeconds(1));
然后订阅该事件流并瞧瞧。
但我也希望它在用户按下 Enter 时立即执行搜索。我不确定如何以“反应性”的方式做到这一点。简单地对 Enter 键事件执行搜索会导致搜索触发两次(一次用于键事件,一次用于文本更改),所以这是我当前的解决方案:
BooleanProperty hasSearched = new SimpleBooleanProperty(false);
EventStream<KeyEvent> enterKeyPressedEvents = EventStreams.eventsOf(textArea, KeyEvent.KEY_PRESSED)
.filter(k -> k.getCode() == KeyCode.ENTER);
AwaitingEventStream<Change<String>> textEvents = EventStreams.changesOf(textArea.textProperty())
.successionEnds(Duration.ofSeconds(1));
subs = Subscription.multi(
//Text changed
textEvents.subscribe(e -> {
if (hasSearched.get()) {
hasSearched.set(false);
System.out.println("ignored text event");
} else {
performSearch(textArea.getText());
}
}),
//Enter key pressed
enterKeyPressedEvents.subscribe(e -> {
e.consume();
if (e.isShiftDown()) {
textArea.insertText(textArea.getCaretPosition(), "\n");
} else {
hasSearched.set(true);
System.out.println("enter pressed");
performSearch(textArea.getText());
if (!textEvents.isPending()) {
hasSearched.set(false);
}
}
})
);
我尝试过使用SuspendableEventStream.suspend()
认为它会“丢弃”所有待处理事件,但它没有按预期工作,待处理事件仍然被发出:
EventStream<KeyEvent> enterKeyPressedEvents = EventStreams.eventsOf(textArea, KeyEvent.KEY_PRESSED)
.filter(k -> k.getCode() == KeyCode.ENTER);
SuspendableEventStream<Change<String>> textEvents = EventStreams.changesOf(textArea.textProperty())
.successionEnds(Duration.ofSeconds(1)).suppressible();
subs = Subscription.multi(
//Text changed
textEvents.subscribe(e -> {
performSearch(textArea.getText());
}),
//Enter key pressed
enterKeyPressedEvents.subscribe(e -> {
e.consume();
if (e.isShiftDown()) {
textArea.insertText(textArea.getCaretPosition(), "\n");
} else {
Guard guard = textEvents.suspend();
System.out.println("enter pressed");
performSearch(textArea.getText());
guard.close();
}
})
);
我怎样才能想出更好(更具反应性?)的解决方案?