将对象添加到可观察数组的开头

问题描述 投票:2回答:2

我有一个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更好地解释了这个问题。

angular rxjs
2个回答
2
投票

我理解使用一个特殊的this._shouldPrepend变量似乎很奇怪,因为它打破了“纯函数”范式。

所以我个人会发出包含信息的对象,无论我要添加它们还是前缀。

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如何处理它。


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

© www.soinside.com 2019 - 2024. All rights reserved.