首页 > 解决方案 > 在 RxJS 中何时使用 tap() 以及何时使用 map()

问题描述

该文档使用以下代码描述了 tap():

import { fromEvent } from 'rxjs';
import { tap, map } from 'rxjs/operators';

const clicks = fromEvent(document, 'click');
const positions = clicks.pipe(
  tap(ev => console.log(ev)),
  map(ev => ev.clientX),
);
positions.subscribe(x => console.log(x));

但我不明白为什么要使用水龙头。难道只是记录。解释说

将每次点击映射到该点击的 clientX 位置,同时记录点击事件

标签: rxjsangular2-observables

解决方案


轻敲

对源 Observable 上的每个发射执行副作用,但返回与源相同的 Observable

例子:

tap(value => console.log(value))

地图

将给定的项目函数应用于源 Observable 发出的每个值,并将结果值作为 Observable 发出。

例子:

map(value => 'prefix' + value)

为什么不使用 map 或其他运算符来处理 log 等副作用

您可以使用 map、scan 和任何其他获取函数并返回单个结果的运算符来实现副作用。这将使您的代码将来很难理解/调试/查找错误。前提是,通常在管道中使用副作用是不好的。如果您需要/想要它并且不希望每个日志记录点都有很多订阅,那么日志记录可能是一个例外。因此,点击可能很有用。您可以将其调整为以下步骤:

  1. 尽量避免副作用
  2. 如果您需要一些(记录),请使用点击来澄清有副作用

你可以但不应该怎么做的例子

switchMap(value => {
  console.log(value); // Side effect 1
  const newValue = foo(value);
  console.log(newValue); // Side effect 2
  return of(newValue);
})

你可以怎么做和应该怎么做的例子

tap(console.log), // Side effect 1
switchMap(value => of(foo(value))),
tap(console.log) // Side effect 2

最后一句话:当您最初编写的代码并没有带来太多好处时。你的项目越大,当其他人试图找到错误时,它会大大节省时间。


推荐阅读