Angular 8 异步管道订阅问题
Angular 8 Async Pipe subscription issue
完整 StackBlitz 示例:https://stackblitz.com/edit/angular8-async-pipe
应用组件模板中有三个相同的组件:
<app-loader></app-loader>
<app-progress></app-progress>
<app-spinner></app-spinner>
每个组件都调度它自己的 NgRx 操作,它使用 NgRx 效果触发 Http 请求并等待其完成:
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { ActionsService } from '../../../services/actions.service';
import * as MockyActions from '../../actions/mocky.actions';
@Component({
selector: 'app-spinner',
templateUrl: './spinner.component.html'
})
export class SpinnerComponent implements OnInit {
progress$: Observable<boolean>;
constructor (
private store: Store<any>,
private actionsService: ActionsService) {}
ngOnInit() {
this.progress$ = this.actionsService
.isInProgress(MockyActions.GetMockySpinner)
.pipe(
map(({status}) => status),
tap((status) => console.log('GetMockySpinner: ', status))
);
this.store.dispatch(MockyActions.GetMockySpinner());
}
}
在每个使用 Async Pipe 的组件中,我想在进行 Http 请求时显示微调器:
<div class="text-center" *ngIf="!(progress$ | async); else progress">
Spinner
</div>
<ng-template #progress>
<div class="text-center">
<span class="spinner spinner-sm"></span>
</div>
</ng-template>
但在这种情况下,只有 <app-spinner></app-spinner>
组件中的微调器在 Http 请求过程中显示。如果应用组件模板中的组件顺序发生变化:
<app-loader></app-loader>
<app-progress></app-progress>
<app-spinner></app-spinner>
<app-loader></app-loader>
在这种情况下,<app-loader></app-loader>
组件中的 Spinner 在 Http 请求过程中显示。因此只有模板中的最后一个组件按预期工作。
那么 Angular 8 中的 Async Pipe 发生了什么变化或者我做错了什么?
完整 StackBlitz 示例:https://stackblitz.com/edit/angular8-async-pipe
你的MockyActions
出了点问题。
改变
this.progress$ = this.actionsService.isInProgress(MockyActions.GetMockyProgress)
...
和
this.progress$ = this.actionsService.isInProgress(MockyActions.GetMockyLoader)
...
到
this.progress$ = this.actionsService.isInProgress(MockyActions.GetMockySpinner)
你的例子工作正常。
您没有为您的应用使用实际状态和缩减程序。 NgRX 要求您同时使用操作和缩减器。您遇到的问题是,当前两个组件订阅了操作主题时,第三个操作就在那里了。您不会监听 NgRX 中发生的操作。相反,你要做的是观察你的状态被动作修改。
这是解决您的问题的有效 stackblitz。
https://stackblitz.com/edit/angular8-async-pipe-xexehj?file=src%2Fapp%2Fapp.module.ts
下面是一些有用的文档。
https://ngrx.io/guide/store/reducers
https://ngrx.io/guide/store
完整 StackBlitz 示例:https://stackblitz.com/edit/angular8-async-pipe
应用组件模板中有三个相同的组件:
<app-loader></app-loader>
<app-progress></app-progress>
<app-spinner></app-spinner>
每个组件都调度它自己的 NgRx 操作,它使用 NgRx 效果触发 Http 请求并等待其完成:
import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { ActionsService } from '../../../services/actions.service';
import * as MockyActions from '../../actions/mocky.actions';
@Component({
selector: 'app-spinner',
templateUrl: './spinner.component.html'
})
export class SpinnerComponent implements OnInit {
progress$: Observable<boolean>;
constructor (
private store: Store<any>,
private actionsService: ActionsService) {}
ngOnInit() {
this.progress$ = this.actionsService
.isInProgress(MockyActions.GetMockySpinner)
.pipe(
map(({status}) => status),
tap((status) => console.log('GetMockySpinner: ', status))
);
this.store.dispatch(MockyActions.GetMockySpinner());
}
}
在每个使用 Async Pipe 的组件中,我想在进行 Http 请求时显示微调器:
<div class="text-center" *ngIf="!(progress$ | async); else progress">
Spinner
</div>
<ng-template #progress>
<div class="text-center">
<span class="spinner spinner-sm"></span>
</div>
</ng-template>
但在这种情况下,只有 <app-spinner></app-spinner>
组件中的微调器在 Http 请求过程中显示。如果应用组件模板中的组件顺序发生变化:
<app-loader></app-loader>
<app-progress></app-progress>
<app-spinner></app-spinner>
<app-loader></app-loader>
在这种情况下,<app-loader></app-loader>
组件中的 Spinner 在 Http 请求过程中显示。因此只有模板中的最后一个组件按预期工作。
那么 Angular 8 中的 Async Pipe 发生了什么变化或者我做错了什么?
完整 StackBlitz 示例:https://stackblitz.com/edit/angular8-async-pipe
你的MockyActions
出了点问题。
改变
this.progress$ = this.actionsService.isInProgress(MockyActions.GetMockyProgress)
...
和
this.progress$ = this.actionsService.isInProgress(MockyActions.GetMockyLoader)
...
到
this.progress$ = this.actionsService.isInProgress(MockyActions.GetMockySpinner)
你的例子工作正常。
您没有为您的应用使用实际状态和缩减程序。 NgRX 要求您同时使用操作和缩减器。您遇到的问题是,当前两个组件订阅了操作主题时,第三个操作就在那里了。您不会监听 NgRX 中发生的操作。相反,你要做的是观察你的状态被动作修改。
这是解决您的问题的有效 stackblitz。
https://stackblitz.com/edit/angular8-async-pipe-xexehj?file=src%2Fapp%2Fapp.module.ts
下面是一些有用的文档。 https://ngrx.io/guide/store/reducers https://ngrx.io/guide/store