我有三个观察点:

query$: Observable<string> = this.q$.pipe(tap(() => this.page$.next(0));
filter$: Observable<number> = this.f$.pipe(tap(() => this.page$.next(0));
page$ = new BehaviorSubject<number>(0);

combinetLatest({
  query: this.query$,
  filter: this.filter$,
  page: this.page$
})
.pipe(
  switchMap(({ query, filter, page }) => {
    ...
  })
);

每当它们中的任何一个发出时,我都必须将它们的值顺流而下.但是,使用combineLatest会导致至少多两个冗余emits .我试图连入distinctUntilChanged(),但这也会在某些时候产生一个多余的emits .

请协助:(或者可能我的整个方法/ idea 是不正确的,我不应该将page$作为query$filter$的副作用?

从某种意义上讲,我不在乎"页面"的值,因为在"查询"或"过滤"emits 的情况下,它总是0.但我确实关心"page"发出时的"Query"和"Filter"值.因此,它似乎变成了两个独立的可观察到的东西?但我想将其分配给组件属性,以便将其与模板中的"异步"管道一起使用,因此对于两个不同的可观察对象,我无法...

Update:很抱歉大惊小怪;我本应该详细说明的. 在输入字段输入时发出query$. filter$在 Select 框更改时发出. 代表"页码"的page$在点击"加载更多"按钮时发出.

所以我的 idea 是有一个组件属性:

objects$: Observable<object[]> = combineLatest({
  query: this.query$,
  filter: this.filter$,
  page: this.page$
}).pipe(
  switchMap(({ query, filter, page }) => this.someService.sendApiRequest(query, filter, page)),
  scan((acc, { objects}) => {
    if (page !== 0) {
      return [...acc, ...objects];
    } else {
      return objects;
    }
  }, [])
);

并在带有async个管道的模板中使用它:

<div *ngFor="let x of objects$ | async">...</div>

基本上,只要用户输入查询、更改筛选器或加载更多项,就可以获取结果.

推荐答案

也许这样的方法会奏效:

combineLatest({ query: this.q$, filter: this.f$ }).pipe(
  switchMap(({query, filter}) => this.page$.pipe(
    map((p, i) => i === 0 ? 0 : p)),
    map(page => ({query, filter, page}))
  ))
);

其 idea 是,您的comineLatest只从queryfilter开始,然后切换到page.map运算符中的第二个参数指示订阅page$的"排放指数",它将从0开始,并在每次page$排放时增加.所以,我们在第一次emits 时emits 0,在那之后emits page$的值.每当filter$query$发出时,SwitchMap将创建新的订阅,这意味着对page$进行新的内部订阅,这意味着索引将从0开始.

您可以添加另一个switchMap来进行API调用,或者直接将第二个map转换为switchMap:

combineLatest({ query: this.q$, filter: this.f$ }).pipe(
  switchMap(({query, filter}) => this.page$.pipe(
    map((p, i) => i === 0 ? 0 : p)),
    switchMap(page => this.callApi(query, filter, page))
  ))
);

最新情况:

如果您不需要指定实际页码,只需要加载下一页,而不是page$页,则可以使用:

private loadMore$ = new BehaviorSubject<void>(undefined);

视图的可观测性可能如下所示:

items$ = combineLatest({ query: this.q$, filter: this.f$ }).pipe(
  switchMap(({query, filter}) => this.loadMore$.pipe(
    switchMap((_, page) => this.callApi(query, filter, page)),
    scan((all, items) => all.concat(items), [])
  )),
);

在这里,我们简单地使用loadMore$作为触发器,并使用内部可观察到的"emits 指数"作为页码.由于loadMore$是一个BehaviorSubject,它会在订阅时emits 一次,所以它不需要点击按钮就可以第一次emits .然后,每次后续时间loadMore$发出(when your button is clicked),它将再次发出,并且SwitchMap将执行具有递增索引的API调用(page number).

这是一张StackBlitz example美元.

Javascript相关问答推荐

React Native平面列表自动滚动

有什么(最佳)方法可以从模块中获取脚本模块的多姆元素吗?

fs. writeFile()vs fs.writeFile()vs fs.appendFile()

从mat—country—select获取整个Country数组

角色 map 集/spritebook动画,用户输入不停止在键上相位器3

有没有可能使滑动img动画以更快的速度连续?

显示图—如何在图例项上添加删除线效果?

如何根据当前打开的BottomTab Screeb动态加载React组件?

JS,当你点击卡片下方的绿色空间,而它是在它的背后转动时,

使用Nuxt Apollo在Piniastore 中获取产品细节

根据一个条件,如何从处理过的数组中移除一项并将其移动到另一个数组?

当用户点击保存按钮时,如何实现任务的更改?

回溯替代方式

当标题被点击时,如何使内容出现在另一个div上?

有没有一种直接的方法可以深度嵌套在一个JavaScript对象中?

Cherrio JS返回父div的所有图像SRC

使用Java脚本替换字符串中的小文本格式hashtag

JSON Web令牌(JWT)错误:RSA密钥对的签名无效

如何从Reaction-Redux中来自API调用的数据中筛选值

使用Java脚本筛选数组中最接近值最小的所有项