如何触发可观察的流,该流被用作异步管?

发布于 2025-01-31 21:22:54 字数 2877 浏览 4 评论 0原文

我有一个上下文,我需要与Angular Group选项卡并行获取数据。打开选项卡时,我希望它以获取数据,显示进程中的加载,显示数据后显示数据,或显示错误(如果有),则全部在HTML上。 触发器

我的组件自由触发该过程。

private queryInboxTriggerObs: BehaviorSubject<any> = new BehaviorSubject('');
queryInboxTrigger$ = this.queryInboxTriggerObs.asObservable();

ngOnInit() {
    const getInbox$ = timer(6e3).pipe(tap(res => console.log(`getInbox$`, res)), map(() => ({ inbox: 1 }))); // fake api
    this.timeout$ = timer(5e3).pipe(take(1), map(() => { throw new Error('timeout!!!') }));
    this.queryInbox$ = concat(
        of({ type: 'start' }),
        of(1).pipe(
            switchMap(() => race(this.timeout$, getInbox$)),
            tap(res => console.log(`race`, res)),
            map(res => ({type: 'finish', value: res}))
        )
    );
    this.inbox$ = this.queryInboxTrigger$.pipe(exhaustMap(() => this.queryInbox$));

    this.initInbox();
}

initInbox() {
    this.queryInboxTriggerObs.next('');
}

onLoadInboxClick() {
    this.initInbox();
}

我希望用 是我的http请求,inbox $是我的异步可观察的,queryInboxTrigger $是我的触发器。

内部initinbox(),我仅调用this.queryinboxtriggerobs.next(''');,我希望它每次调用initinbox时都会触发我的获取数据过程(),例如onloadinboxClick。不幸的是,我的触发器仅在ngoninit上首次工作,我无法通过继续执行this.queryinboxtriggerobs.next(''')来再次触发该过程,通过单击或切换选项卡,我需要在这里提供帮助。例如,当timeout $排放值时,我的html再次显示文本加载数据,onloadinboxClick呼叫,我希望queryinbox $能够再次运行

我的组件.html

<mat-tab-group mat-align-tabs="start" (selectedIndexChange)="selectedIndexChange($event)">
<mat-tab label="Inbox">
    <ng-container *ngIf="inbox$ | withLoading | async as inbox">
        <ng-container *ngIf="inbox.error">
            <p>Data not found. <a (click)="onLoadInboxClick()">Try again</a></p>
        </ng-container>
        <ng-container *ngIf="inbox.value">
            <span>Inbox: {{ inbox.value.inbox }}</span>
        </ng-container>
        <ng-container *ngIf="inbox.loading">
            <p>Loading...</p>
        </ng-container>
    </ng-container>
</mat-tab>
<mat-tab label="Tab 2">Content 2</mat-tab>
<mat-tab label="Tab 3">Content 3</mat-tab>

和我的自定义异步管

transform(value: any): any {
    return isObservable(value)
            ? value.pipe(
                map((val: any) => {
                    return {
                        loading: val.type === 'start',
                        value: val.type ? val.value : val
                    }
                }),
                startWith({ loading: true }),
                catchError(error => of({ loading: false, error }))
            )
            : value;
}

I have a context where I need to fetch data in parallel along side with angular group tab. When a tab opened, I'd like it to fetch data, show loading in process, show data when it's done fetching, or show error (if any), all upon html. And I wish to trigger that process freely with a triggerer

My component.ts:

private queryInboxTriggerObs: BehaviorSubject<any> = new BehaviorSubject('');
queryInboxTrigger$ = this.queryInboxTriggerObs.asObservable();

ngOnInit() {
    const getInbox$ = timer(6e3).pipe(tap(res => console.log(`getInbox

I have a context where I need to fetch data in parallel along side with angular group tab. When a tab opened, I'd like it to fetch data, show loading in process, show data when it's done fetching, or show error (if any), all upon html. And I wish to trigger that process freely with a triggerer

My component.ts:

, res)), map(() => ({ inbox: 1 }))); // fake api this.timeout$ = timer(5e3).pipe(take(1), map(() => { throw new Error('timeout!!!') })); this.queryInbox$ = concat( of({ type: 'start' }), of(1).pipe( switchMap(() => race(this.timeout$, getInbox$)), tap(res => console.log(`race`, res)), map(res => ({type: 'finish', value: res})) ) ); this.inbox$ = this.queryInboxTrigger$.pipe(exhaustMap(() => this.queryInbox$)); this.initInbox(); } initInbox() { this.queryInboxTriggerObs.next(''); } onLoadInboxClick() { this.initInbox(); }

where using exhaustMap because I do not wish to restart process when tab switched, keep it going till it's done,getInbox$ is my http request, inbox$ is my async observable, and queryInboxTrigger$ is my trigger to the process.

inside initInbox(), I only call this.queryInboxTriggerObs.next('');, and I expect it to trigger my fetching data process everytime I call initInbox(), like within onLoadInboxClick. Unfortunately, my trigger only work the first time on ngOnInit, I cannot trigger the process again by keep doing this.queryInboxTriggerObs.next('') by clicking or switching tab, I need help here. For example, when timeout$ emits value, my html shows text load data again and onLoadInboxClick called, I expect queryInbox$ to run again

My component.html

<mat-tab-group mat-align-tabs="start" (selectedIndexChange)="selectedIndexChange($event)">
<mat-tab label="Inbox">
    <ng-container *ngIf="inbox$ | withLoading | async as inbox">
        <ng-container *ngIf="inbox.error">
            <p>Data not found. <a (click)="onLoadInboxClick()">Try again</a></p>
        </ng-container>
        <ng-container *ngIf="inbox.value">
            <span>Inbox: {{ inbox.value.inbox }}</span>
        </ng-container>
        <ng-container *ngIf="inbox.loading">
            <p>Loading...</p>
        </ng-container>
    </ng-container>
</mat-tab>
<mat-tab label="Tab 2">Content 2</mat-tab>
<mat-tab label="Tab 3">Content 3</mat-tab>

and my custom async pipe

transform(value: any): any {
    return isObservable(value)
            ? value.pipe(
                map((val: any) => {
                    return {
                        loading: val.type === 'start',
                        value: val.type ? val.value : val
                    }
                }),
                startWith({ loading: true }),
                catchError(error => of({ loading: false, error }))
            )
            : value;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

故人爱我别走 2025-02-07 21:22:54

看来我的自定义管道正在引起问题。当我这样更新代码

this.queryInbox$ = concat(
        of({ type: 'start' }),
        of(1).pipe(
            switchMap(() => race(this.timeout$, this.getInbox$)),
            tap(res => console.log(`race`, res)),
            map(res => ({type: 'finish', value: res})),
            catchError(err => of({ type: 'error' }))
        )
    );

并相应地更新我的HTML(删除载荷管)

<mat-tab-group mat-align-tabs="start" (selectedIndexChange)="selectedIndexChange($event)">
<mat-tab label="Hộp thư đến">
    <ng-container *ngIf="inbox$ | async as inbox">
        <ng-container *ngIf="inbox.type === 'error'">
            <p>Data not found. <a (click)="onLoadInboxClick()">Try again</a></p>
        </ng-container>
        <ng-container *ngIf="inbox.type === 'finish'">
            <span>Inbox: {{ inbox.value.inbox }}</span>
        </ng-container>
        <ng-container *ngIf="inbox.type === 'start'">
            <p>Loading...</p>
        </ng-container>
    </ng-container>
</mat-tab>
<mat-tab label="Hộp thư đi">Content 2</mat-tab>
<mat-tab label="Tạo thư mới">Content 3</mat-tab>

时,一切都按预期工作。

It seems like my custom pipe is causing problem. When I update code like this

this.queryInbox$ = concat(
        of({ type: 'start' }),
        of(1).pipe(
            switchMap(() => race(this.timeout$, this.getInbox$)),
            tap(res => console.log(`race`, res)),
            map(res => ({type: 'finish', value: res})),
            catchError(err => of({ type: 'error' }))
        )
    );

and update my html accordingly (remove withLoading pipe)

<mat-tab-group mat-align-tabs="start" (selectedIndexChange)="selectedIndexChange($event)">
<mat-tab label="Hộp thư đến">
    <ng-container *ngIf="inbox$ | async as inbox">
        <ng-container *ngIf="inbox.type === 'error'">
            <p>Data not found. <a (click)="onLoadInboxClick()">Try again</a></p>
        </ng-container>
        <ng-container *ngIf="inbox.type === 'finish'">
            <span>Inbox: {{ inbox.value.inbox }}</span>
        </ng-container>
        <ng-container *ngIf="inbox.type === 'start'">
            <p>Loading...</p>
        </ng-container>
    </ng-container>
</mat-tab>
<mat-tab label="Hộp thư đi">Content 2</mat-tab>
<mat-tab label="Tạo thư mới">Content 3</mat-tab>

Everything works as expected.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文