【问题标题】:What is the difference between tap and map in RxJS?RxJS 中的 tap 和 map 有什么区别?
【发布时间】:2020-08-01 08:20:50
【问题描述】:

我从文章中看到了不同之处,但要点看起来像这样。

所以使用tap 我可以更改变量,例如如果我输入x=3+4 然后它会更改变量的值,那么我可以说有一个副作用。

但是使用map 我可以更改循环每个值的值,不是吗? 你能指出它们有哪些显着差异吗?

点按

RxJS tap 对源 Observable 发出的每个值执行副作用,并返回一个与源 Observable 相同的 Observable,直到没有错误为止。

地图

map 是一个 RxJS 可管道操作符。 map 将给定函数应用于源 Observable 发出的每个元素,并将结果值作为 Observable 发出

【问题讨论】:

    标签: rxjs


    【解决方案1】:

    映射函数接受一个事物并返回另一个事物。例如我可以构建一个接受10并返回11的函数,接受11并返回12等。

    const inc = n => n + 1;
    

    Array#map 将这种映射函数应用于数组的所有元素,但“映射”并不意味着“迭代”。

    在 RxJS 中,当数据被发送到流时,它会通过一系列操作符:

    • map 运算符将简单地将函数应用于该数据并返回结果。
    • tap 运算符接收一个数据,将一个函数应用于该数据但返回原始数据,如果该函数不想返回结果,tap 将忽略它。

    这是一个例子:

    • 我们将10 推送到流a$tap 只需记录值。我们知道console.log 总是返回undefined,但这很好,因为tap 只是返回它的参数。
    • 我们将10 推送到流b$,它通过map(inc) 应用inc10 返回11

    const a$ = of(10).pipe(tap(n => console.log(`tap: ${n}`)));
    const b$ = of(10).pipe(map(inc));
    
    a$.subscribe(n => console.log(`n from a$: ${n}`));
    b$.subscribe(n => console.log(`n from b$: ${n}`));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.min.js"></script>
    
    <script>
    const {of} = rxjs;
    const {map, tap} = rxjs.operators;
    
    const inc = n => n + 1;
    </script>

    【讨论】:

    • 在哪里可以使用tap,在哪里可以使用地图?
    • 非常感谢你的解释和你给出的例子:)
    【解决方案2】:

    tapmap 都是 RxJS 运算符,RxJS 运算符只是对数据执行一些操作的函数。

    它们都是pipeable operators,它将输入作为 Observable,执行一些操作并返回一个输出 observable。

    地图和点击的区别:

    map 是一个管道操作符,它接受一个输入 observable,对其执行一些操作并返回一个新的操作 observable。例如

    const source$ = of(1,2,3) // observable which will emit 1,2,3
    // It take an input observable and return a new observable which will emit square of input values. 
    // So, the output observable will emit 1,4,9
    const mapSource$ = of(1,2,3)
                        .pipe(map(value => value * value)) 
    

    另一方面,tap 运算符接受输入 observable 执行某些操作并返回相同的输入 observable。

    const source$ = of(1,2,3) // observable which will emit 1,2,3
    // It take an input observable and return a same observable after console value.
    // So, the output observable will emit 1,2,3
    const tapSource$ = of(1,2,3)
                        .pipe(tap(value => console.log(value))) 
    

    【讨论】:

    • 在哪里可以使用tap,在哪里可以使用地图?
    【解决方案3】:
    • tap 的目的是执行一个动作保持相同的值 可观察到的

    • map 的目的是转换 可观察的

    const messagesCount$ = newMessages$
    .pipe(tap(messages => notificationService.notify('You have ' + message.length + ' message(s)')))
    .pipe(map(messages => messages.length))
    

    【讨论】:

      【解决方案4】:

      点击应该用于通知,记录非上下文/关键的副作用。

      这就像“窥视”到“管道”。数据保持不变,你可以用它做点什么。一些数据进入,你看,同样的数据出来。

      Map 用于“管道”中数据的转换/映射。一些数据进来,不同/转换的数据出来。

      【讨论】:

        【解决方案5】:

        您可以将tap 运算符视为一个 void 函数,无论它对输入值做什么都不会改变原始值

        const source = of(1, 2, 3, 4, 5);
        
        // here we are manipulating the input value but the output value of the observable still the same 
        const example = source.pipe(
          tap(val => val + 100),
        );
        
        // output: 1, 2, 3, 4, 5
        const subscribe = example.subscribe(val => console.log(val));
        

        另一方面,如果我们使用 map 操作符对 observable 的输入值进行任何操作,它将改变输出值

        const example = source.pipe(
          map(val => val + 100)
        );
        
        // output: 101, 102, 103, 104, 105
        const subscribe = example.subscribe(val => console.log(val));
        

        【讨论】:

          【解决方案6】:

          除了其他人所说的之外,在 Rxjs 7.4 中,tap 现在多了三个订阅处理程序,因此您可以使用它来获得订阅、取消订阅和完成的通知:

          https://github.com/ReactiveX/rxjs/commit/eb26cbc4488c9953cdde565b598b1dbdeeeee9ea#diff-93cd3ac7329d72ed4ded62c6cbae17b6bdceb643fa7c1faa6f389729773364cc

          这非常适合用于调试目的,因此您可以使用点击来了解更多关于您的流发生了什么的信息。

          例子:

          const subscription = subject
          .pipe(
            tap({
              subscribe: () => console.log('subscribe'),
              next: (value) => console.log(`next ${value}`),
              error: (err) => console.log(`error: ${err.message}`),
              complete: () => console.log('complete'),
              unsubscribe: () => console.log('unsubscribe'),
              finalize: () => console.log('finalize'),
            })
          )
          .subscribe();
          

          【讨论】:

            猜你喜欢
            • 2023-03-04
            • 1970-01-01
            • 1970-01-01
            • 2017-05-30
            • 2017-03-22
            • 2022-06-26
            • 1970-01-01
            • 2018-05-12
            • 1970-01-01
            相关资源
            最近更新 更多