【问题标题】:rxjs reduce does not continuerxjs减少不继续
【发布时间】:2019-01-10 05:18:40
【问题描述】:

我在 Angular 7 应用程序中有以下设置:

@Effect({dispatch:false})
LoadInstances$ = this.actions$.pipe(
ofType(fromAppAction.AppActionTypes.LoadInstances),
take(1), // <-- solved my problem
switchMap((action: fromAppAction.LoadInstances) =>
      this.entityService.GetInstances()
    ),

switchMap(instances=>from(instances)), // flatten the array to single values
flatMap( // combine the instance with its UserData
    (inst)=>this.entityService.GetCurrentUserInfo().pipe(take(1)),
    (inst,usr)=>({...inst, UserData:usr})
),
flatMap(
  (inst)=>this.entityService.GetUserPersonalSettings(inst.id).pipe(take(1)),
  (inst,settings)=>({...inst, Settings:settings})
),
tap(result=>console.log('before reduce:',result)), // <-- this gets called 3 times (I have 3 instances)
reduce<Instance>((a, c) => [...a, c], []), // accumulate all results to one array
tap(result=>console.log('instances: ', result)), // <-- this gets never called
...

本质上,我有一个实例数组,将它们展平,为每个实例调用 GetCurrentUserInfo 和 GetUserPersonalSettings,将结果作为属性添加到实例中,然后希望将它们累积回 Instance[]。

到目前为止,这有效,只是 reduce 函数没有继续。我知道这是因为其他 observables 之一没有完成。但怎么可能呢? 最初的 from(instances) 遍历数组,然后应该完成,是吗?并且对 GetPersonalSettings 的调用只是简单的 httpClient.get() 调用,根据文档,它们是在成功调用后完成的单值可观察对象。

谁能帮帮我?

[编辑] scan 在这里不是一个选项,因为我需要完整的实例数组才能继续。 [Edit2] toArray 和reduce 有同样的问题,它只在前一个Observable(s?) 完成时才发出结果。

无论如何:我不想更改此设置,因为它基本上可以正常工作。我只想了解哪个 Observable 没有完成以及为什么。这将解决我的问题。

【问题讨论】:

  • 如果尝试过扫描,它将为实例数组中的每个项目生成一个输出,如下所示: [inst1] [inst1, inst2] [inst1, inst2, inst3] 但我只想要完整的结果数组,其中包含 所有 个实例。
  • “不继续”是什么意思?你从tap(result=&gt;console.log('instances: ', result)) 得到一个结果,还是根本没有?
  • 不,最后一次点击不会被调用,只有'before reduce'
  • Reduce 不断接收项目,直到 observable 完成。你的 observables 何时完成是否清楚?
  • 这正是我的问题!在我的理解中,所有的 observables 都完成了,但显然不是,我不明白为什么。

标签: angular rxjs ngrx-effects


【解决方案1】:

最近我了解了运算符toArray,可能会简化您的代码。 您的流未完成,因为第一个 switchMap 之前的流未完成

/* What is here? Probably still open stream? */
switchMap((action: fromAppAction.LoadInstances) =>
  this.entityService.GetInstances()
),

快速尝试将first()take(1) 放在第一个switchMap 之前

【讨论】:

  • 我认为 switchMap 会取消订阅以前的 observable 并在链中开始一些全新的东西。这不是真的吗?这实际上是一个ngrx效果。我已经编辑了我的第一篇文章以显示 switchMap 之前的代码行。 ToArray 和 reduce 有同样的问题,它只在 observable 完成时才发出一个值,但在我的例子中,最大的问题是:哪个 observable 没有完成?
  • 您的代码对我来说看起来不错,在您的情况下,您使用的是take(1),所以无论您使用的是switchMap 还是mergeMap,它都定义了如何合并内部的策略如果外部流中有更多事件,则流事件。尝试在末尾添加catchError,可能您在 GetBlaBla 方法之一中出现错误。我创建了类似的示例,它可以工作stackblitz.com/edit/rxjs-esfjjy?devtoolsheight=60
  • 我在代码中添加了 take(1) 但不知何故没有编译。现在可以了。谢谢大家,尤其是马克西姆。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-19
  • 1970-01-01
  • 2018-11-30
  • 1970-01-01
相关资源
最近更新 更多