Typescript 为什么在Rxjs中需要Tap运算符
我是Rxjs新手,正在观看David Acosta关于Rxjs运算符的教程之一。 在这篇文章中,他说当我们不需要接触可观测数据时,我们可以使用tap操作符。 因此,tap函数中的数据不会更改 我写了下面的代码Typescript 为什么在Rxjs中需要Tap运算符,typescript,rxjs,Typescript,Rxjs,我是Rxjs新手,正在观看David Acosta关于Rxjs运算符的教程之一。 在这篇文章中,他说当我们不需要接触可观测数据时,我们可以使用tap操作符。 因此,tap函数中的数据不会更改 我写了下面的代码 const source = Observable.of("david"); source.pipe( tap(x => x.toString().toUpperCase()) ).subscribe(x => console.log(x));
const source = Observable.of("david");
source.pipe(
tap(x => x.toString().toUpperCase())
).subscribe(x => console.log(x));
我得到的输出是david
。
但我想知道
source.subscribe(x => console.log(x));
给出相同的输出david
。那我们为什么需要水龙头接线员呢。
这对我来说有点神秘,我无法找到合适的资源来解释TAP
操作符
有谁能向我详细解释一下这一点,并向我推荐一些Rxjs操作符的好教程或文档吗 1-存储/查看可观察流的值:
const source = Observable.of("david");
let name;
source.pipe(
tap(x => name = x)
).subscribe(x => console.log(x));
console.log('variable name: ', name);
2-在管道上的某个位置(而不是在订阅上)执行一些副作用:
注意:在代码中使用tap运算符执行副作用时要小心。有些是合理的和正确的,但其他的可以通过对.subscribe回调执行您的副作用来解决
希望这有帮助 Tap运算符通常用于两种使用情形: 1-存储/查看可观察流的值:
const source = Observable.of("david");
let name;
source.pipe(
tap(x => name = x)
).subscribe(x => console.log(x));
console.log('variable name: ', name);
2-在管道上的某个位置(而不是在订阅上)执行一些副作用:
注意:在代码中使用tap运算符执行副作用时要小心。有些是合理的和正确的,但其他的可以通过对.subscribe回调执行您的副作用来解决
希望这有帮助 例如,当您想做某事时,您可以使用
轻触
,但您不想获取所有值 因此(您只需要一个特定的类型),因此您可以过滤您的流。
例如,您构建的arryay中的数字只能被2整除,您不需要其他数字
但是,使用tap
在很多时候都是一个干净的代码
简单代码参考:
myObservable$ = new Observable(observer => {
observer.next(1);
observer.next(2);
observer.next(3);
observer.next(4);
observer.next(5);
observer.next(6);
observer.complete();
});
this.myObservable$
.pipe(
tap(() => console.log('got Value!')),
filter(value => (value % 2) === 0),
)
.subscribe(value => {
console.log('filtered: ', value);
this.mySpecificArray.push(value);
});
例如,当您想要执行某项操作时,可以使用
轻触
,但您不想获取所有值 因此(您只需要一个特定的类型),因此您可以过滤您的流。
例如,您构建的arryay中的数字只能被2整除,您不需要其他数字
但是,使用tap
在很多时候都是一个干净的代码
简单代码参考:
myObservable$ = new Observable(observer => {
observer.next(1);
observer.next(2);
observer.next(3);
observer.next(4);
observer.next(5);
observer.next(6);
observer.complete();
});
this.myObservable$
.pipe(
tap(() => console.log('got Value!')),
filter(value => (value % 2) === 0),
)
.subscribe(value => {
console.log('filtered: ', value);
this.mySpecificArray.push(value);
});
点击与添加订阅并不完全相同。例如,如果您有一个HTTP服务器的客户端,那么您可能会有一些类似于
function getItems(): Observable<Item[]> {
return makeSomeExpensiveHttpCall()
.map(rsp => doSomeExpensiveParsing(rsp))
.tap(items => console.log(`Received ${items.length} items`));
}
函数getItems():可观察{
返回makeSomeExpensiveHttpCall()
.map(rsp=>doSomeExpensiveParsing(rsp))
.tap(items=>console.log(`Received${items.length}items`);
}
…乍一看相当于
function getItems(): Observable<Item[]> {
const result = return makeSomeExpensiveHttpCall()
.map(rsp => doSomeExpensiveParsing(rsp));
result.subscribe(items => {
console.log(`Received ${items.length} items`);
});
return result;
}
函数getItems():可观察{
const result=返回makeSomeExpensiveHttpCall()
.map(rsp=>doSomeExpensiveParsing(rsp));
结果。订阅(项目=>{
log(`Received${items.length}items`);
});
返回结果;
}
但是,按照当前编写的方式,每次调用
subscribe
时,它都将执行makeSomeExpensiveHttpCall
和doSomeExpensiveParsing
。因此,在第二个示例中,您可能会调用这些函数两次,而不是一次。您将向服务器发送两个相同的HTTP请求。我们当然希望避免这种情况。点击与添加订阅并不完全相同。例如,如果您有一个HTTP服务器的客户端,那么您可能会有一些类似于
function getItems(): Observable<Item[]> {
return makeSomeExpensiveHttpCall()
.map(rsp => doSomeExpensiveParsing(rsp))
.tap(items => console.log(`Received ${items.length} items`));
}
函数getItems():可观察{
返回makeSomeExpensiveHttpCall()
.map(rsp=>doSomeExpensiveParsing(rsp))
.tap(items=>console.log(`Received${items.length}items`);
}
…乍一看相当于
function getItems(): Observable<Item[]> {
const result = return makeSomeExpensiveHttpCall()
.map(rsp => doSomeExpensiveParsing(rsp));
result.subscribe(items => {
console.log(`Received ${items.length} items`);
});
return result;
}
函数getItems():可观察{
const result=返回makeSomeExpensiveHttpCall()
.map(rsp=>doSomeExpensiveParsing(rsp));
结果。订阅(项目=>{
log(`Received${items.length}items`);
});
返回结果;
}
但是,按照当前编写的方式,每次调用
subscribe
时,它都将执行makeSomeExpensiveHttpCall
和doSomeExpensiveParsing
。因此,在第二个示例中,您可能会调用这些函数两次,而不是一次。您将向服务器发送两个相同的HTTP请求。我们当然希望避免这种情况。并非特定于Rxjs,但通常使用tap作为调试工具,在更改序列的这一点上检查数据。您可能能够对数据进行变异并继续,但这通常不是一个好主意。管道/流的不同实现可能有不同的原理,或者实际上可能完全不允许它,或者允许它没有问题。一般来说,你不想在点击时进行转换,因为它可能会扰乱其他一些操作。那么点击的副作用是什么呢。正如您所说的,不想进行转换
。这取决于实现。例如,在Java示例中,编译器可能会优化流上的.tap
操作。如果依赖它,那么代码可能会随机失效。在其他地方,这可能会打乱不同的优化。或者,这可能会扰乱操作的并行化。最一般的答案是,对数据的操作应该通过以下方式完成-这简化了优化操作的数学过程,并允许了琐碎的多线程,因为您需要更改状态。例如,如果您希望将数据保存在本地存储中,但不想在可观察的管道中转换数据,则可以使用tap(x=>localStorage。