简体   繁体   English

Angular 8 异步 Pipe 订阅问题

[英]Angular 8 Async Pipe subscription issue

Full StackBlitz example: https://stackblitz.com/edit/angular8-async-pipe完整的 StackBlitz 示例: https://stackblitz.com/edit/angular8-async-pipe

There are three identical components in app component template: app组件模板中有三个相同的组件:

<app-loader></app-loader>
<app-progress></app-progress>
<app-spinner></app-spinner>

Every component dispatches it's own NgRx action, which fires an Http request using NgRx effects and waits for its completion:每个组件调度它自己的 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());
  }
}

In every component using Async Pipe I want to show spinner while Http request is in progress:在使用异步 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>

But only spinner in <app-spinner></app-spinner> component is displaying during Http request progress in this case.但在这种情况下,在 Http 请求进度期间,仅显示<app-spinner></app-spinner>组件中的微调器。 And if the sequence of components in app component template changed:如果应用组件模板中的组件顺序发生了变化:

<app-loader></app-loader>
<app-progress></app-progress>
<app-spinner></app-spinner>
<app-loader></app-loader>

Spinner in <app-loader></app-loader> component is displaying during Http request progress in this case.在这种情况下, <app-loader></app-loader>组件中的微调器在 Http 请求进度期间显示。 So only last component in template works as expected.所以只有模板中的最后一个组件按预期工作。

So what's changed with Async Pipe in Angular 8 or what I'm doing wrong?那么 Angular 8 中的异步 Pipe 发生了什么变化,或者我做错了什么?

Full StackBlitz example: https://stackblitz.com/edit/angular8-async-pipe完整的 StackBlitz 示例: https://stackblitz.com/edit/angular8-async-pipe

You aren't using an actual state and reducer for your app.您没有为您的应用程序使用实际的 state 和减速器。 NgRX requires that you use both actions and reducers. NgRX 要求你同时使用 action 和 reducer。 The problem you are having is that by the time the first two components have subscribed to the actions subject, it is the third action that is there.您遇到的问题是,当前两个组件订阅操作主题时,第三个操作已经存在。 You don't listen for actions to occur in NgRX.你不会监听 NgRX 中发生的动作。 What you do instead is watch for your state to be modified by the action.相反,您要做的是观察您的 state 是否被该操作修改。

Here is a working stackblitz that fixes your issue.这是一个可以解决您的问题的有效堆栈闪电战。

https://stackblitz.com/edit/angular8-async-pipe-xexehj?file=src%2Fapp%2Fapp.module.ts https://stackblitz.com/edit/angular8-async-pipe-xexehj?file=src%2Fapp%2Fapp.module.ts

Below is some helpful documentation.下面是一些有用的文档。 https://ngrx.io/guide/store/reducers https://ngrx.io/guide/store https://ngrx.io/guide/store/reducers https://ngrx.io/guide/store

Something is wrong with your MockyActions .您的MockyActions有问题。

Change改变

this.progress$ = this.actionsService.isInProgress(MockyActions.GetMockyProgress)
...

and

this.progress$ = this.actionsService.isInProgress(MockyActions.GetMockyLoader)
...

To

this.progress$ = this.actionsService.isInProgress(MockyActions.GetMockySpinner)

and you example works fine.你的例子工作正常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM