typescript - rxjs penomboran halaman dengan langganan ke setiap halaman


Kami sedang membuat pertanyaan graphql melalui websocket untuk mempunyai langganan kepada senarai entiti. Kami menggunakan penomboran kerana senarai itu sepatutnya boleh digulung tanpa had. Kami juga ingin melihat perubahan yang dibuat dalam pangkalan data secara masa nyata dalam senarai di bahagian hadapan.

Senarai ini boleh ditapis, disusun dan dihalaman.

Kami mempunyai kelas SelectParams yang membantu kami untuk melakukan itu:

export class SelectParams {
    page = 0;
    query = '';
    sort: Sort = { sortBy: 'creationDate', sortOrder: 'DESC' };
    take = 30;
}

Kemudian apabila kita ingin melanggan senarai, kita hanya memberikan selectParams$=Observable<SelectParams> untuk mendapatkan senarai yang "reaktif" dan bertindak balas terhadap perubahan dalam selectParams$. Ini digunakan seperti ini:

    this.items$ = this.featureSrv.selectMany(this.selectParams$)

Di bawah hud, selectMany berfungsi seperti ini:

// when we call selectMany we just push the params to the pipeline
selectMany(params$: Observable<SelectParams> = of(new SelectParams())): Observable<T[]> {
    this.selectManyParams$.next(params$);
    return this.selectMany$;
}

// subject where we push params to sort, paginate and filter
selectManyParams$ = new ReplaySubject<Observable<SelectParams>>(1);
// when the params change then so does this observable, which is returned by the selectMany function
selectMany$ = this.selectManyParams$.asObservable().pipe(
    // retrieve params from their observable form
    flatMap(params$ => params$),
    // when the params haven't changed we shouldn't do anything
    distinctUntilChanged(),
    // then we query graphql to get a suscription to some part of the data
    switchMap(({ page, sort, query, take }: SelectParams) => {
    // the selectMany here is a subscription to some data on the server
        return this.apolloWrapper.selectMany(this.gql, page, sort, query, take ).pipe(
    // we add page data so we can use it in the scan
            map(data => ({ data, page }) as any)
        );
    }),
    // we append the result if page was incremented
    // else we just return the result
    scan((acc: any, curr: any) => curr.page === 0 ? curr.data : acc.concat(curr.data), [])
);

Kaedah this.apolloWrapper.selectMany adalah kaedah yang kami cipta yang hanya melakukan langganan melalui websocket kepada sebahagian data. Katakan kami mempunyai page=0 maka this.apolloWrapper.selectMany akan mengembalikan langganan kepada sebahagian data pertama, kemudian apabila page=1, this.apolloWrapper.selectMany mengembalikan langganan kepada sebahagian data kedua.

Masalah timbul apabila kita memuatkan halaman kedua dan membuat pengubahsuaian pada item di potongan pertama, scan kemudian dicetuskan dan item ditambah semula ke hujung senarai.