我正在从 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/