我有一个Angular组件,当容器的滚动位置到达底部时,延迟将数据加载到Observable<Item[]>
到BehaviorSubject<Item[]>
。
初始化项目列表所需的属性和init()
函数看起来像
private _itemList: BehaviorSubject<Item[]>;
private _done = new BehaviorSubject(false);
private _loading = new BehaviorSubject(false);
private _page: number;
itemList: Observable<Item[]>;
init() {
this._page = 0;
this._itemList = new BehaviorSubject([])
this.mapAndUpdate();
this.itemList = this._itemList.asObservable()
.scan((acc, val) => {
return acc.concat(val);
});
}
以及实际获取数据的函数
mapAndUpdate() {
if (this._done.value || this._loading.value) {
return;
}
this._loading.next(true);
const offset = this._page * 20;
const limit = 20;
return this.service.getItems(limit, offset)
.do(res => {
this._itemList.next(res.items);
this._loading.next(false);
if (!res.items.length) {
this._done.next(true);
}
}).subscribe();
}
在同一个组件中,我订阅了可以发出新项目的实时推送事件,这些新项目应该添加到数组的开头而不是数组的末尾。
subscribeToItemsChannel() {
this.pusherService.getItemsChannel().bind('new-item', (res: any) => {
const item = res.item as Item;
// Emitting the item with next() will only add it to the end of the array
this._itemList.next([item]);
});
}
我尝试使用我在实时函数处理程序中设置的布尔值shouldPrepend
和
.scan((acc, val) => {
if(this._shouldPrepend) {
return val.concat(acc);
} else {
return acc.concat(val);
}
});
确实将新项目添加到开头,但也会混淆数组其余部分的顺序,并且它也不会像正确的rxjs方式那样。
我如何在任何给定的随机时刻将对象添加到Observable<array>
?
Here is a JSBin可以更好地解释问题。
答案 0 :(得分:2)
我理解使用一个特殊的this._shouldPrepend
变量看起来很奇怪,因为它打破了&#34;纯函数&#34;范例
因此,我个人会发出包含信息的对象,无论我要添加或附加什么信息。
enum Action { Append, Prepend };
...
numberList = bSubject
.scan((acc, val) => val.action === Action.Prepend
? [val.value, ...acc]
: [...acc, val.value]
);
...
setInterval(() => {
console.log('Fetching data... Numberlist is now: ');
bSubject.next({ action: Action.Append, value: i});
i++;
}, 3000);
您的最新演示:http://jsbin.com/wasihog/edit?js,console
最终,如果您不想改变发布值的方式,您可以拥有两个合并的主题。一个预先设定价值的,另一个追加价值。
const append$ = new Subject();
const prepend$ = new Subject();
Observable.merge(
append$.map(value => ({ action: Action.Append, value })),
prepend$.map(value => ({ action: Action.Prepend, value })),
)
你可以看到你发出像append$.next(1)
这样的值,并且该值将被一个告诉scan
如何处理它的对象包裹。
答案 1 :(得分:0)
我对这件事有些迟了,但是您似乎想要 startWith 。
//emit (1,2,3)
const source = of(1, 2, 3);
//start with 0
const example = source.pipe(startWith(0));
//output: 0,1,2,3
const subscribe = example.subscribe(val => console.log(val));
此代码示例来自https://www.learnrxjs.io/operators/combination/startwith.html