RxJs运算符在每次迭代结束时无条件执行

时间:2019-01-11 20:00:27

标签: javascript rxjs observable

是否有Rx运算符或复合运算来确保每次可观察到的发射都在逻辑上执行最后一次?

我们假设以下情况:

  1. 无尽或连续的顺序
  2. filter()这样的条件逻辑可以跳过某些排放
  3. 类似于 doAlways() 的运算符
  4. 中,每次迭代结束时的一些逻辑

请参考以下代码示例中带编号的注释

注释:

  • finalize()将要求序列终止(违反第1页)
  • iif()中的
  • if或常规switchMap()是一个选项,但会使代码更不可读

代码段说明:步骤(3)应始终按迭代执行,即最后执行,即我们希望始终以类似doAlways()的运算符而不是{ {1}}

tap()

3 个答案:

答案 0 :(得分:1)

不存在这样的运算符,这是因为它不存在。过滤出一个值后,所得的可观察值不再发出该值。任何“下游”操作员只是根本不知道它的存在。

为说明起见,您将switchMap包含到某些服务中,这取决于发出的值。出于显而易见的原因,如果没有值可以打开,则无法在逻辑上应用运算符。

您将不得不“标记”每个值而不是对其进行过滤,并将过滤器推迟到tap调用之后,但是即使那样,切换到另一个可观察的场景仍需要更详细的要求。


可将其视为放置物品的传送带。每个操作员都是安全带穿过的房间。在每个房间内,工人可以决定如何处理每个物品:修改,取走,放入新物品等。但是,每个工人只能看到传送带带来的东西-他们不知道还有其他房间在他们之前或在那里做了什么。

要实现您想要的目标,最后一个房间的工人必须知道他从未收到的物品,这需要他们没有的其他知识。

答案 1 :(得分:1)

不,由于过滤的通知将永远不会传递,因此您无法提出要求。您将需要一种全新的通知类型,该通知类型不会被您所描述的其他任何运算符使用。

现在,这是一个不建议使用的想法。您可以滥用error通知来跳过某些运算符,但这会干扰任何其他错误处理,因此您不应这样做...

const sub = interval(1000).pipe(            
  tap(a => console.log('starting', a)),
  mergeMap(b => b % 100 === 0 ? of(b) : throwError(b)),
  switchMap(c => dataService.update(c)),
  catchError(b => of(b)),
  tap(d => console.log('finishing', d))
)

请注意,根据情况,我们不使用filter而是映射到nexterror通知。错误自然会被运算符忽略,并被tapsubscribecatchError消耗。这是一种在物品上贴标签的方法,以便工人知道他们不应该触摸它(类似于Ingo所描述的)

答案 2 :(得分:1)

我会用partition将其分成2个流,然后它们会合并回去。

https://stackblitz.com/edit/rxjs-8z9jit?file=index.ts

import { of, interval, merge } from 'rxjs';
import { tap, switchMap, partition, share } from 'rxjs/operators';

const dataService = { update: z => of(z /*posts data to back-end*/) };

const [sub, rest] = interval(1000).pipe(
  tap(a => console.log('starting', a)),
  share(),
  partition(b => b % 2 === 0)
);

merge(
    sub.pipe(
      switchMap(c => dataService.update(c)),
      tap(() => console.log('Ok'))
    ), 
    rest
)
.pipe(tap(d => console.log('finishing', d)))
.subscribe(x => console.log(x));