Как добавить одно наблюдаемое к другому? - PullRequest
3 голосов
/ 10 ноября 2019

Я хочу инициализировать 12 пользователей в моем списке ${this.url}/users?offset=${offset}&limit=12, но при прокрутке это смещение должно увеличиться на 8 пользователей.

Я хочу использовать для этого бесконечную прокрутку. Моя проблема в том, что я использую observables(userList), и я не знаю, как добавить новый список из 8 членов к старому. В уроках в интернете все используют concat(), но это для массивов: / Я сам пытался что-то просто вызвать смещение целого списка + 8, когда loadMore имеет значение true, но это почему-то не работает.

Мой код:

service.ts

  // get a list of users
  getList(offset= 0): Observable<any> {
    return this.http.get(`${this.url}/users?offset=${offset}&limit=12`);
  }

page.ts

@ViewChild(IonInfiniteScroll) infiniteScroll: IonInfiniteScroll;
userList: Observable<any>;
offset = 0;
...
 getAllUsers(loadMore = false, event?) {
    if (loadMore) {
      this.userList = this.userService.getList(this.offset += 8) //new 8 users
    .pipe(map(response => response.results));
    }
    this.userList = this.userService.getList(this.offset) // initials 12 users
    .pipe(map(response => response.results));
    if (event) {
      event.target.complete();
      console.log(event);
      console.log(loadMore);
    }
  }

page.html

...
  </ion-item>


    </ion-list>
    <ion-infinite-scroll threshold="100px" (ionInfinite)="getAllUsers(true, $event)">
        <ion-infinite-scroll-content
          loadingSpinner="crescing"
          loadingText="Loading more data...">
        </ion-infinite-scroll-content>
      </ion-infinite-scroll>

</ion-slide>

<ion-slide>

Ответы [ 3 ]

2 голосов
/ 10 ноября 2019

используйте Объединить , чтобы объединить несколько observables в одну наблюдаемую:

getAllUsers(loadMore = false, event?) {
    if (loadMore) {
      const newUserList$ = this.userService.getList(this.offset += 8) //new 8 users
    .pipe(map(response => response.results));
    this.userList = merge(this.userList, newUserList$); // merge observables

    }
    this.userList = this.userService.getList(this.offset) // initials 12 users
    .pipe(map(response => response.results));
    if (event) {
      event.target.complete();
      console.log(event);
      console.log(loadMore);
    }
  }

Обновить

Из вашего URL, возможно, вам следует удалить параметр limit:

  getList(offset= 0): Observable<any> {
    return this.http.get(`${this.url}/users?offset=${offset}`);
  }
1 голос
/ 10 ноября 2019

Как упоминалось в других ответах, это хороший вариант использования для оператора scan.

Однако мы должны найти способ продолжать добавлять (накапливать) данные, когда пользователь выполняет прокрутку. Я думаю, что это может быть достигнуто с помощью BehaviorSubject, который будет выдавать значения на каждом свитке. Я выбрал этот тип предмета, потому что вы также хотите указать начальное значение.

const loadUsersSubject = new BehaviorSubject<number>(12);
let userList$/* : Observable<any>; */ // Uncomment this if used inside the template along with the async pipe
let internalCnt = 0;

const generateUsers = (n: number) => {
  return of(
    Array.from({ length: n }, ((_, i) => ({ user: `user${++internalCnt}` })))
  );
}

userList$ = loadUsersSubject
  .pipe(
    flatMap(numOfUsers => generateUsers(numOfUsers)),
    scan((acc, crt) => [...acc, ...crt])
  )
  .subscribe(console.log)


// Scrolling after 1s..
timer(1000)
  .subscribe(() => {
    loadUsersSubject.next(8);
  });


// Scrolling after 3s..
timer(3000)
  .subscribe(() => {
    loadUsersSubject.next(8);
  });

StackBlitz

0 голосов
/ 10 ноября 2019

Вот как оператор scan может использовать состояние, которое дополняется следующими запросами

https://stackblitz.com/edit/rxjs-h91d9u?devtoolsheight=60

import { of, Observable } from 'rxjs'; 
import { map, scan } from 'rxjs/operators';


const source = new Observable((observer) => {
  observer.next(['Hello', 'World']);

  setTimeout(() => {
    observer.next(['will', 'concatenate']);
  }, 1000)

   setTimeout(() => {
    observer.next(['also', 'will', 'concatenate']);
  }, 2000)
}).pipe(
    scan(
      (acc, val) => acc.concat(val),
      []
    )
);

source.subscribe(x => console.log(x));
...