在回调之前和之后添加日志记录的 rxjs 运算符

rxjs operator that adds logging before and after a callback

我正在尝试打开这个:

/* ...inside a pipe */
tap(() => logData('my process')),
tap(() => someCallback()),
tap(() => logDataEnd('my process'),
/* pipe continues */

进入一个接受回调 () => someCallback() 并在其前后添加日志记录副作用的新运算符。我的日志记录函数使用 performance.now(),当我只使用显式 tap 版本时,它们按预期工作*,但我的 none 操作员做同样的事情。

预期结果

使用我的运算符的管道:

of(null).pipe(
  withLogging(() => callbackA()),
  withLogging(() => callbackB()),
  /* etc. */
)

应该生成如下所示的日志:

Action A start
Action A end
Action B start
Action B end
...

但是我得到这个:

Action A start
Action B start
/* ... rest of the pipe */
Action A end
Action B end

通过查看时间戳,我可以看到 end 日志的时间戳正确,但 begin 的时间戳太早了。

我尝试过以不同的方式使用 defer,但结果没有改变。

我试过的

withLogging<T, R>(project: (value :T) => R): OperatorFunction<T, R> {
  return (source: Observable<T>) =>
  defer(() => of(startLogging())).pipe(
    flatMap(() => source),
    tap(() => stopLogging())
  );
}

我试过用 defer 包裹整个管道,或者只是记录过程的开始,或者做 of(null).pipe 然后将所有效果放在一起。我什至尝试过完全不使用 defer,只是返回一个以 null 开头的管道。没有产生所需的行为。

除非你的 someCallback() 本身是异步的 and/or 你以后会想要 flatMap 它,我不会在这里实现新的运算符。一个简单的香草高阶函数将很好地满足您的需求。

function withLogging<A extends unknown[], C>(
  cb: (this: C, ...args: A) => void
) {
  return function(this: C, ...args: A) {
    console.log("before");
    cb.call(this, ...args);
    console.log("after");
  };
}

// snip

function someCallback() {
    console.log('Hello!');
}

someObs$.tap(withLogging(someCallback)); // before, Hello!, after for each pushed element