【问题标题】:How to append one observable to another?如何将一个可观察对象附加到另一个?
【发布时间】:2020-03-06 03:15:42
【问题描述】:

我想在我的列表${this.url}/users?offset=${offset}&limit=12 中初始化 12 个用户,但是随着滚动,这个偏移量应该增加 8 个用户。

我想为此使用无限滚动。我的问题是我正在使用observables(userList),但我不知道如何将 8 个成员的新列表附加到旧列表中。在互联网上的教程中,所有人都使用concat(),但这是针对数组的:/我自己尝试了一些方法,当 loadMore 为真时调用整个列表 + 8 偏移量,但不知何故不起作用。

我的代码:

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>

【问题讨论】:

  • 使用scan 运算符。它作为一个 reducer 工作,但也在每个值发出后发出值(不等待 observable 完成)
  • @Sergey 你能把它写到我的代码中作为答案吗?我真的会知道如何应用它,也不知道我写的函数会留下什么。

标签: javascript angular typescript ionic-framework observable


【解决方案1】:

正如其他答案中提到的,这是 scan 运算符的一个很好的用例。

但是,我们必须找到一种方法来在用户滚动时继续添加(累积)数据。我认为这可以通过使用BehaviorSubject 来实现,该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

【讨论】:

    【解决方案2】:

    使用Merge 将多个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 中删除限制参数:

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

    【讨论】:

    • 我的列表仍然没有加载更多的用户:/向下滚动时。我的代码中是否还有其他错误。我真的不知道我可以进一步尝试什么
    【解决方案3】:

    这里是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));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-25
      • 2019-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多