我只想在获得第一个发出的值时执行 tap()
就像是:
Observable
.pipe(
tap(() => { /* execute only when I get the first emitted value */ })
)
.subscribe(() => {
// .....
})
Run Code Online (Sandbox Code Playgroud)
jal*_*jal 17
您可以在像concatMap. 与其他方法不同,这对于所选索引是完全灵活的。假设您想要点击第二次发射index === 1或任何谓词,例如index % 2 === 0
// these are because of using rxjs from CDN in code snippet, ignore them
const {of, interval} = rxjs;
const {take, tap, concatMap} = rxjs.operators;
// main code
const stream = interval(250).pipe(take(4))
stream.pipe(
concatMap((value, index) => index === 0
? of(value).pipe(
tap(() => console.log('tap'))
)
: of(value)
)
)
.subscribe(x => console.log(x));Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/@reactivex/rxjs@6.x/dist/global/rxjs.umd.js"></script>Run Code Online (Sandbox Code Playgroud)
Gog*_*eli 12
如果我正确理解您的想法,您只想tap()在流订阅开始时执行,而不是其他时间。这是我的自定义运算符:
import { Observable, of } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';
export function startWithTap<T>(callback: () => void) {
return (source: Observable<T>) =>
of({}).pipe(tap(callback), switchMap((o) => source));
}
Run Code Online (Sandbox Code Playgroud)
例如,此运算符的用法是:
this.api.getData().pipe(
startWithTap(() => this.loading.start()),
)
Run Code Online (Sandbox Code Playgroud)
这是我的实际代码示例,当有人订阅由 api 服务(通过 httpClient)创建的 Observable 时,加载开始。
更新
使用 this 而不是上面的实现,因为这个只使用defer, 而不是使用of, tapand switchMap:
export function startWithTap<T>(callback: () => void) {
return (source: Observable<T>) =>
defer(() => {
callback();
return source;
});
}
Run Code Online (Sandbox Code Playgroud)
我喜欢jal 的回答方法,并建议将其包装在自己的运算符中:
export function tapOnce<T>(tapFn: (t: T) => void, tapIndex = 0): OperatorFunction<T, T> {
return source$ => source$.pipe(concatMap((value, index) => {
if (index === tapIndex) {
tapFn(value);
}
return of(value);
}));
}
Run Code Online (Sandbox Code Playgroud)
用法如下:
stream.pipe(tapOnce(() => console.log('tapping once'), 1));
Run Code Online (Sandbox Code Playgroud)
这甚至可以进一步抽象为一个运算符,该运算符采用一个函数来确定是否应该根据给定的值/索引进行点击:
export function tapWhen<T>(tapFn: (t: T) => void, evaluateFn: (index: number, t: T) => boolean): OperatorFunction<T, T> {
return source$ => source$.pipe(concatMap((value, index) => {
if (evaluateFn(index, value)) {
tapFn(value);
}
return of(value);
}));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10064 次 |
| 最近记录: |