【问题标题】:Hide spinner component when Observable completedObservable 完成时隐藏微调器组件
【发布时间】:2018-05-23 21:56:38
【问题描述】:

我试图在某个可观察对象开始后立即在按钮中显示一个微调器,并在它结束后再次隐藏它。

经过数小时的研究,我有点迷失了如何实现它(我知道这里有几个帖子,但似乎都没有帮助,甚至经常提到的 angular-2-busy 或其中一个叉子也没有真的好用)

所以会有工作流

我有一个指令/组件,我可以通过@Input 向它提供一个 Observable。 指令应该在 Observable 启动后立即显示微调器(或者我可以只使用 click 事件)。 并且它应该在订阅完成后再次隐藏微调器。

注意:下面的示例是简化的(不涉及微调器等),但确切地显示了问题所在。

export class AppComponent {
  name = 'Angular 6';
  test: Observable<any>;

  constructor(private http: HttpClient) {

    const obs = of(true);
    this.test = obs.pipe(tap(() => console.log('tap1')), flatMap(() => {
      return this.http.get('https://httpbin.org/get');
    })
    );
  }

  demo() {
    this.test.subscribe((state: any) => console.log(state));
  }
}

export class HelloComponent implements OnChanges {
  @Input() name: string;

  @Input()
  obs: Observable<any>;

  ngOnChanges(changes: SimpleChanges): void {

    if (changes.obs) {
      this.obs.pipe(map(() => console.log('component')));
    }
  }
}

here is the stackblitz 这说明了我试图完成的工作以及它目前不起作用

当我在 hello-component 中调用 subscribe 时,它显然会立即执行每个管道方法,这不是我想要的。

当我不调用 subscribe 时,pipe 运算符会创建一个新的 subscription,它显然永远不会被执行。

所需的行为是控制台中的以下输出。

  • “tap1”
  • http 调用的结果
  • “组件”

我觉得我错过了一些非常明显的东西。 关于如何解决这个问题的任何想法?

【问题讨论】:

标签: javascript angular rxjs


【解决方案1】:

不完全确定你想怎么做,但我扩展了你的Stackbiltz with a solution here

主要部分是这样的:

showSpinner = false;
  demo() {
    this.showSpinner = true;
    this.test.subscribe(
      tick => (console.log("event from observable")),
      error => (console.log("error from observable")),
      () => {console.log("Observable finished"); this.showSpinner=false;}
    )
  }

observable 有 3 种事件类型:“tick”将获取每个 Observable.next,在错误时调用错误,在最后一个事件之后(如果事件流有结束)将调用最后一个最终调用。你应该利用它。

编辑: 您也可以在 Observable 定义中使用管道和水龙头:

  this.obs.pipe(
        tap(
          event => (console.log("observable event tick")),
          error => (console.log("observable error")),
          () => (console.log("observable finish"))
        )
      );

Edit2:我将代码移动到this example here中的hello.component.ts

Edit3:您不能“倾听听众的意见”。但是,您可以更改您的逻辑,以实现想要的行为,请参阅this updated example

基本上,您需要显式调用组件,以告知它旋转事件的开始和结束事件。可以使用@ViewChild查看组件,然后直接调用它们的公共方法。

【讨论】:

  • 我需要能够在hello-component 中显示/隐藏微调器,它(当前)采用Observable 作为输入。我只需将您的代码从demo() 移到它会立即执行的组件内。问题是如何在我的组件中使用 observable 作为 Input 并在我的组件中对其完成做出反应。
  • 我将代码移到了另一个组件,它工作得很好。请检查一下
  • 也许我的问题/问题表述错误。尽管此方法按预期工作,但我最初的问题是我不希望在hello-component 中出现点击事件,但我想对我通过@Input 提供的可观察对象的完成“做出反应”
  • 啊我现在明白了。更新了我的答案。
【解决方案2】:

使用async 和模板可以让 Spinner 等案例的工作变得更轻松:

<ng-container *ngIf="person$ | async as person; else loading">
    {{person.name}}
</ng-container>
<ng-template #loading>
    loading...
</ng-template>

Here is the stackblitz.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2013-04-19
    • 2016-12-16
    • 1970-01-01
    相关资源
    最近更新 更多