RxJS中的Wrap运算符,因此可以将其应用于物化流

时间:2018-12-23 20:33:46

标签: rxjs reactivex

我正在寻找一种在流运算符之间跟踪值“路由”的方法。我的物化流在Notification对象(例如valueId属性)上具有其他元数据。它的定义看起来像这样:

const x = stream.pipe(
  materialize(),
  map(x => Object.assign(x, {valueId: randomInt()}))
);

现在,我需要包装应用于x的运算符。假设我需要使用map(x => x * 2),但是我不能这样做:

x.pipe(dematerialize(), map(x => x * 2))

因为我将丢失我的元数据。如何制作自动换行功能,该功能将适用于任何运算符,并且仍然保留我的其他元数据?

x.pipe(wrap(map(x => x * 2)))

我想到了这样的事情:

function wrap<T, R>(
  operator: OperatorFunction<T, R>
): (source: Observable<TaggedValue<T>>) => Observable<TaggedValue<R>> {
  return source =>
    source.pipe(
      switchMap(x =>
        of(x).pipe(
          dematerialize(),
          operator,
          materialize(),
          map(z => Object.assign(z, { valueId: x.valueId }))
        )
      )
    );
}

但是它会从of()生成伪造的完整消息。 样本:https://stackblitz.com/edit/rxjs-fhv54p

3 个答案:

答案 0 :(得分:1)

使用of的方法中的问题在于,of的完整通知已实现,并作为value传递给source的观察者。

尝试一下:

function wrap<T, R>(op: OperatorFunction<T, R>):
  (source: Observable<any>) => Observable<any> {
  return source => {
    return source.pipe(
      switchMap(x => of(x)
        .pipe(
          dematerialize(),
          op,
          map(y => ({value: y, uuid: x.uuid}))
        )
      ),
      materialize(),
      map((x: any) => Object.assign(x, {
        value: x.value ? x.value.value : undefined,
        uuid: x.value ? x.value.uuid: undefined
      })),
    )
  }
}

演示:https://stackblitz.com/edit/rxjs-gxj7zl

答案 1 :(得分:0)

您可以这样做

const stream$ = stream$.pipe(map((data=> ({...data, x: data.x + 1}))))

或将其移至自动换行功能

const mapProp = (propName, fn) => stream$.pipe(map((data=> ({...data, [propName]: fn(data[propName])}))))

//then
const stream$ = stream$.pipe(mapProp('x', x => x+1 ))

如果您想将其用于除map

之外的其他内容
const mapProp = (propName, fn) => stream$.pipe(
    mergeMap(data =>
      of(data[propName])
        .pipe(
           fn,
           map(newPropValue => ({ ...data, propName: newPropValue })
        )
    )
)

//Usage 
const stream$ = stream$.pipe(mapProp('x', map(x => x+1)))

答案 2 :(得分:0)

目前,我想到了使用包装功能状态“保留”数据的想法。尽管我到目前为止发现它是最安全的实现,但我并不真的喜欢它的“副作用”性质。

Dataset<B> dataset2

但是它不起作用,因为元数据被随机覆盖。