Rxjs Reactivejs自动完成分叉管道

Rxjs Reactivejs自动完成分叉管道,rxjs,Rxjs,我正在学习一些Reactivejs教程,我正在用rx.js实现autocomplete 它看起来很棒,但我想知道如何实现一些功能。 请看以下代码: const $title = $('#title'); // input element const $results = $('#result'); Rx.Observable.fromEvent($title, 'keyup') .map(event => event.target.value.trim()) .disti

我正在学习一些Reactivejs教程,我正在用rx.js实现autocomplete

它看起来很棒,但我想知道如何实现一些功能。 请看以下代码:

const $title = $('#title'); // input element
const $results = $('#result');

Rx.Observable.fromEvent($title, 'keyup')
    .map(event => event.target.value.trim())
    .distinctUntilChanged()
    .debounceTime(500)
    .switchMap(getItems) // getItems sends request for result based on input value and returns promise
    .subscribe(items => {
        $results.empty();
        $results.append(items.map(record => $('<li> /').text(record)));
    });
const$title=$('#title');//输入元素
常量$results=$(“#result”);
Rx.Observable.fromEvent($title,‘keyup’)
.map(event=>event.target.value.trim())
.distinctUntilChanged()
.debounceTime(500)
.switchMap(getItems)//getItems根据输入值发送结果请求并返回承诺
.订阅(项目=>{
$results.empty();
$results.append(items.map(record=>$).text(record));
});
这非常有效,我可以得到输入值更改的更新列表。 但若用户完全清除了输入,我想阻止发送请求。 我可以使用过滤器实现它:

Rx.Observable.fromEvent($title, 'keyup')
    .map(event => event.target.value.trim())
    .filter(query => query.length > 0)
    .distinctUntilChanged()
    .debounceTime(500)
    .switchMap(getItems)
    .subscribe(items => {
        $results.empty();
        $results.append(items.map(record => $('<li> /').text(record)));
    });
Rx.Observable.fromEvent($title,“keyup”)
.map(event=>event.target.value.trim())
.filter(query=>query.length>0)
.distinctUntilChanged()
.debounceTime(500)
.switchMap(getItems)
.订阅(项目=>{
$results.empty();
$results.append(items.map(record=>$).text(record));
});
但若用户已经清除了这个输入,我不想发送额外的请求,我想加载默认的项目列表

我怎样才能做到这一点

有没有一种方法可以捕获可观察集合中的新条目,如果它是空字符串,则会中断处理管道,但仍以某种方式订阅它

 Rx.Observable.fromEvent($title, 'keyup')
        .map(event => event.target.value.trim())

        // CHECK IF INPUT VALUE IS EMPTY STRING, NAD IF IT IS
        // PREVENT PIPELINE STEPS BELOW FROM BEING PROCESSED.
        // ALSO SHOW DEFAULT LIST ITEMS

        .distinctUntilChanged()
        .debounceTime(500)
        .switchMap(getItems)
        .subscribe(items => {
            $results.empty();
            $results.append(items.map(record => $('<li> /').text(record)));
        });
Rx.Observable.fromEvent($title,“keyup”)
.map(event=>event.target.value.trim())
//检查输入值是否为空字符串,如果为空则为NAD
//防止处理下面的管道步骤。
//还显示默认列表项
.distinctUntilChanged()
.debounceTime(500)
.switchMap(getItems)
.订阅(项目=>{
$results.empty();
$results.append(items.map(record=>$).text(record));
});
我尝试过以这种方式实现它:

const query$ = Rx.Observable.fromEvent($title, 'keyup')
    .map(event => event.target.value.trim());

query$
    .filter(query => query.length > 0)
    .distinctUntilChanged()
    .debounceTime(500)
    .switchMap(getItems)
    .subscribe(items => {
        $results.empty();
        $results.append(items.map(record => $('<li> /').text(record)));
    });

query$.subscribe(query => {
    if (!query.length) {
        $results.text('default list'); // this list will still be overwritten with last fetch result
    }
});
const query$=Rx.Observable.fromEvent($title,'keyup'))
.map(event=>event.target.value.trim());
质疑$
.filter(query=>query.length>0)
.distinctUntilChanged()
.debounceTime(500)
.switchMap(getItems)
.订阅(项目=>{
$results.empty();
$results.append(items.map(record=>$).text(record));
});
查询$.subscribe(查询=>{
if(!query.length){
$results.text('default list');//此列表仍将被上次提取结果覆盖
}
});

但查询的最后一个响应仍然调用我的订阅侦听器并用结果填充列表。

最简单的解决方案是:

Rx.Observable.fromEvent($title,“keyup”)
.map(event=>event.target.value.trim())
.distinctUntilChanged()
.debounceTime(500)
.switchMap((搜索)=>{
如果(!search)返回Rx.Observable.of(null);
返回getItems(搜索);
})
.订阅(项目=>{
$results.empty();
if(items==null){
$results.text(“默认列表”);
}否则{
$results.append(items.map(record=>$).text(record));
}
});
解释

所有的魔法都在
开关映射
操作符中。基本上,它用回调提供的源替代了可观察的源。当下一个事件到达
switchMap
时,它完成先前创建的observable并创建新的observable

在您的例子中,它用于激发服务器请求用户输入,如果用户在[request]仍在运行时更改输入,则取消以前的请求

实现的问题是
switchMap
对空输入一无所知。事件链:

  • 用户按“a”
    • 首先,流去Bounces然后开始从服务器加载项目
    • 第二个流忽略事件
  • 用户清除输入
    • 第一个流使用
      过滤器过滤掉事件(事件未到达
      开关映射
    • 第二个流显示默认项
  • 调用带有项目和第一个流的订阅逻辑的服务器响应。因此,将覆盖默认项

您可以创建一个可观测的公共源,共享它,然后创建两个订阅-一个为空,一个为非空结果。您可以恢复在subscribe中调用的相同效果函数。它将删除代码中的ifs,使其更具可读性和可重用性

诸如此类:

let input = document.getElementById('inp');
let obs$ = Rx.Observable.fromEvent(input, 'keyup')
  .map(event => event.target.value.trim())
  .share();

function doEffect(result) {
  console.log(result)
}

obs$
  .filter(query => query.length > 0)
  .switchMap(x=>Rx.Observable.of([x.toUpperCase(), x.toUpperCase()]))
  .subscribe(x=>doEffect(x))

obs$
  .filter(query => query.length === 0)
  .mapTo([])
  .subscribe(x=>doSideEffect(x))

你检查你的解决方案了吗?它与OP的one-
查询的最后一个响应仍然调用我的订阅侦听器并用结果填充列表的缺陷相同。是的。您可以添加默认列表逻辑,而不是.mapTo([])键入“aa”(等待响应),然后用退格清除它。非常有用,谢谢!我想知道为什么最后一个响应没有调用我的订阅侦听器。你能解释一下吗?@user2359820,我已经更新了答案。希望现在一切都清楚了。