我只想在获得第一个发射值时执行tap()
类似的东西:
result
答案 0 :(得分:3)
如果有人感兴趣,这是 tapN 的非常简单实现。因此,它将为每个排放执行指定的回调函数,直到排放数量等于nEmissions。为了仅对第一个元素执行tap()函数,您可以执行 tapN(1),但是您也可以使用tapN(3)对3秒钟的发射执行tap。 >
/* Executes the specified callback function for each emission until the number of emissions is equal to nEmissions*/
export const tapN = <T>(nEmissions, callback: (T) => void) => (source$: Observable<T>): Observable<T> =>
defer(() => {
let counter = 0;
return source$.pipe(tap((item) => {
if (counter < nEmissions) {
callback(item);
counter++;
}
}));
});
在您的代码中:
Observable
.pipe(
tapN(1, () => { /* this code would be only executed on the first emitted value */ })
)
.subscribe(() => {
// .....
})
答案 1 :(得分:2)
我喜欢 jal's answer 的方法,并建议将其包装在自己的运算符中:
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);
}));
}
用法如下:
stream.pipe(tapOnce(() => console.log('tapping once'), 1));
这甚至可以进一步抽象为一个运算符,该运算符采用一个函数来确定是否应该根据给定的值/索引进行挖掘:
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);
}));
}
答案 2 :(得分:1)
您可以在地图操作符中使用索引,例如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));
<script src="https://unpkg.com/@reactivex/rxjs@6.x/dist/global/rxjs.umd.js"></script>
答案 3 :(得分:0)
除了已经提到的选项之外,您还使用multicast
。
multicast(new Subject(), s => concat(
s.pipe(
take(1),
tap(v => console.log('tap', v)),
),
s
)
答案 4 :(得分:0)
您可以像下面这样共享()您的主要Observable:
git clone git@github.com:username/repo.git
cd repo
touch some_file
git commit -am "message"
git push origin master
https://stackblitz.com/edit/typescript-qpnbkm?embed=1&file=index.ts
这是一个类似learn-rxjs
的示例答案 5 :(得分:-1)
(更新我之前的错误答案)
基于Cartant的评论和链接,他已经完成了创建操作符的工作,该操作符位于'rxjs-etc'包中。一个基于他的操作员的解决方案是安装“ rxjs-etc”,然后:
import { initial } from 'rxjs-etc/operators';
observable$.pipe(
initial(src$ => src$.pipe(tap(() => {/* execute only on first value */})))
).
subscribe(() => {
// .....
})
有效的StackBlitz示例。
答案 6 :(得分:-1)
如果我正确理解了您的想法,则只在流订阅开始时执行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));
}
例如,使用此运算符的方式将是:
this.api.getData().pipe(
startWithTap(() => this.loading.start()),
)
这是我实际的代码示例,其中当某人开始加载时 订阅由api服务创建的Observable(通过httpClient)。