带有函数返回 Observable 和异步管道的模板绑定 [英] Template binding with function return Observable and async pipe

查看:27
本文介绍了带有函数返回 Observable 和异步管道的模板绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意这是

但是,如果我将 .pipe(delay(1)) 添加到 foo$():

 foo$(): Observable{返回(延迟").管道(延迟(1));}

它不会工作并在控制台日志中保留aaa".

参见 https://stackblitz.com/edit/angular-qbhkg3

解决方案

从模板调用的方法,在每个变更检测周期都会调用.因为您使用的是 async 管道,所以每次发出都会触发更改检测.所以基本上你正在创建一个无限循环,这就是它永远不会显示值的原因,因为更改检测永远不会完成:

  1. 查看初始化模板调用 foo$()
  2. foo$() 创建一个 -new- observable 并延迟发射
  3. 可观察对象在延迟后发出
  4. emit 从 async 管道内触发变更检测
  5. 更改检测从模板中调用 foo$(),然后我们回到第 2 步

目前还不清楚您想要实现的目标,但我认为您不应该从要在模板中使用的方法中返回 Observables.这些应该是只读类字段:

readonly foo$ = of("Delayed").pipe(delay(1));

然而可以使用一个方法,但你必须确保这个方法返回相同的Observable:

private readonly _foo$: Observable= of("Delayed").pipe(delay(1));foo$(): Observable{console.log('这里');返回 this._foo$;}

示例

因为可观察对象保持不变(===),所以一切都很好.一旦你将 pipe 添加到 Observable 中,你就创建了一个新的引用,然后你又回到了无限循环中.

<小时>

如果你只返回of('delayed'),它不会达到无限循环的原因是因为Observable不是异步的.Observable 会立即向 async 管道返回一个值,当异步管道调用 detectChanges() 时,什么都没有发生,因为它仍然与更改检测处于同一周期触发 foo$() 模板调用的循环.

<小时>

我看到您还链接了您之前发布的一个涉及使用装饰器的问题.您应该将该装饰器更改为类字段装饰器,然后您可以执行以下操作:

@NeedsElement(sp(115621), ap(116215))readonly insuranceType$!: Observable;

我想我可以想出一种方法让它与方法调用一起工作,但在我深入研究之前,我首先想知道为什么你首先希望它成为方法调用

Note this is simplified question of Angular template binding with Observable async pipe issue

template:

<div>{{foo()$ | async}}</div>

source code:

import { Component } from "@angular/core";
import { BehaviorSubject, of, Observable } from "rxjs";
import { tap, delay, map, switchMap, concatMap } from "rxjs/operators";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  private index = 0;
  foo$(): Observable<any> {
    console.log("aaa")
    return of("Delayed");
  }
}

The above code works as expected:

However if I added .pipe(delay(1)) to the foo$():

  foo$(): Observable<any> {
    return of("Delayed").pipe(delay(1));
  }

it won't work and keep "aaa" in the console log.

See https://stackblitz.com/edit/angular-qbhkg3

解决方案

A method called from the template, is called every change detection cycle. Because you are using the async pipe, the change detection is triggered with every emit. So basically you are creating an infinite loop and that's why it will never show a value, because the change detection never finishes:

  1. on view init template calls foo$()
  2. foo$() creates a -new- observable and delays the emit
  3. the observable emits after the delay
  4. the emit triggers a change detection from within the async pipe
  5. change detection calls foo$() from the template, and we're back to step 2

It's not really clear what you are trying to achieve, but I don't think you should return Observables from methods to be consumed in templates. These should be readonly class field:

readonly foo$ = of("Delayed").pipe(delay(1));

It is however possible to use a method, but you have to make sure this method returns the same Observable:

private readonly _foo$: Observable<any> = of("Delayed").pipe(delay(1));

foo$(): Observable<any> {
  console.log('here');
  return this._foo$;
}

example

Because the observable object stays the same (===), it's all good in the hood. Once you add a pipe to the Observable you create a new reference and you come back into the infinite loop.


The reason it does not reach the infinite loop if you just return of('delayed'), is because the Observable is not asynchronous this way. The Observable will return a value immediately to the async pipe, and when the async pipe calls detectChanges() nothing really happens, because it's still in the same cycle as the change detection cycle which triggered the foo$() template call.


I see you also linked a previous question you posted which involves the use of a decorator. You should change that decorator to a class field decorator, and you can then do the following:

@NeedsElement(sp(115621), ap(116215))
readonly insuredType$!: Observable<string>;

I think I can think of a way to make it work with a method call, but before I dive into that, I first want to know why you want it to be a method call in the first place

这篇关于带有函数返回 Observable 和异步管道的模板绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆