如何触发可观察的流,该流被用作异步管?
我有一个上下文,我需要与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(`getInboxI 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
看来我的自定义管道正在引起问题。当我这样更新代码
并相应地更新我的HTML(删除载荷管)
时,一切都按预期工作。
It seems like my custom pipe is causing problem. When I update code like this
and update my html accordingly (remove withLoading pipe)
Everything works as expected.