rest - RxJs:从服务器请求列表,消耗值,当我们几乎没有值时重新请求

标签 rest http rxjs observable rxjs5

我正在从 REST api 获取项目列表。用户通过单击与每个人进行交互,当只有几个未使用时,我想重复请求以获取更多项目。我正在尝试使用适当的 RxJs (5) 面向流的方法来做到这一点。

所以,像这样:

var userClick$ = Observable.fromEvent(button.nativeElement, 'click');

var needToExtend$ = new BehaviorSubject(1);

var list$ = needToExtend$
            .flatMap( () => this.http.get("http://myserver/get-list") )
            .flatMap( x => x['list'] );

var itemsUsed$ = userClick$.zip(list$, (click, item) => item);
itemsUsed$.subscribe( item => use(item) );

然后,在必要时触发重新加载:

list$.subscribe(
    if (list$.isEmpty()) {
        needToExtend$.next(1);
    }
)

这最后一点是错误的,手动重新触发似乎不是很“面向流”,即使它确实按预期工作。有什么想法吗?

这类似于 Rxjs - Consume API output and re-query when cache is empty但我无法对 API 返回的列表的长度做出假设,我想在列表完全消耗之前重新请求。而且那里的解决方案感觉有点太聪明了。一定有更易读的方法,对吧?

最佳答案

这样的事情怎么样:

const LIST_LIMIT = 3;
userClick$ = Observable.fromEvent(button.nativeElement, 'click');
list$ = this.http.get("http://myserver/get-list").map(r => r.list);

clickCounter$ = this.userClick$.scan((acc: number, val) => acc + 1, 0);

getList$ = new BehaviorSubject([]);

this.getList$
    .switchMap(previousList => this.list$)
    .switchMap(list => this.clickCounter$, (list, clickCount) => { return {list, clickCount}; })
    .filter(({list, clickCount}) => clickCount >= list.length - LIST_LIMIT)
    .map(({list, clickCount}) => list)
    .subscribe(this.getList$);

这里的逻辑,如果你定义了一个列表 getter 流,以及一个触发它的信号。

首先,信号导致 switchMap 获取一个新列表,然后将其馈送到另一个重新订阅点击计数器的 switchmap。您将两个流的结果组合起来并将其提供给过滤器,它仅在点击次数大于或等于列表长度减去 3(或任何您想要的)时发出。然后信号被订阅到整个流,以便它自己重新触发。

编辑:最大的弱点是您需要在副作用中而不是在订阅或异步管道中设置列表值(用于显示)。您可以重新排列它并进行多播:

const LIST_LIMIT = 3;
userClick$ = Observable.fromEvent(button.nativeElement, 'click');
list$ = this.http.get("http://myserver/get-list").map(r => r.list);

clickCounter$: Observable<number> = this.userClick$.scan((acc: number, val) => acc + 1, 0).startWith(0);

getList$ = new BehaviorSubject([]);

refresh$ = this.getList$
        .switchMap(list => this.clickCounter$
                               .filter(clickCount => list.length <= clickCount + LIST_LIMIT)
                               .first(), 
            (list, clickCount) => list)
        .switchMap(previousList => this.list$)
        .multicast(() => this.getList$);

this.refresh$.connect();
this.refresh$.subscribe(e => console.log(e));

这种方式有一些优点,但可能“可读性”稍差。这些部分大部分是相同的,但是您先去柜台,然后切换到列表提取。然后你多播它以重新启动计数器。

关于rest - RxJs:从服务器请求列表,消耗值,当我们几乎没有值时重新请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47658699/

相关文章:

rest - Golang 中的 RESTful 服务是否应该包含客户端接口(interface)?

javascript - 进行第二次 http 调用并在同一个 Observable 中使用结果

java - 在android上实现http流客户端

http - 将服务器发送的事件与 HTTP2 一起使用时是否仍然存在实际的 6 个连接限制?

javascript - 推荐使用或不使用Subject

javascript - 卡在使用 RxJS 删除计数器应用程序中的所有内容

java - 通过 JAX-RS 实现 REST 服务的可重用性

rest - 为什么angular app调用rest服务时端口号被剪掉了

java - REST API 设计 - 获取多条(1000)条记录

http - 负载平衡 Web 套接字和长轮询