AsyncPipe 在函数返回间隔时不起作用

huangapple go评论73阅读模式
英文:

AsyncPipe not working when interval is returned by a function

问题

以下是翻译好的部分:

component.ts

import {interval} from "rxjs";

export class CalendarComponent implements OnInit {
  interval: any;

  ngOnInit() {
    this.interval = interval(1000);
  }

  myInterval() {
    return interval(1000);
  }
}

component.html

INTERVAL : {{interval | async}} // 显示每秒递增的间隔
FUNCTION : {{myInterval() | async}} // 不起作用
英文:

So I'm messing up a little bit with Observers and I can't understand why methods that returns interval can't display the observers data using the AsyncPipe

component.ts

import {interval} from "rxjs";

export class CalendarComponent implements OnInit {
  interval: any;

  ngOnInit() {
    this.interval = interval(1000);
  }

  myInterval() {
    return interval(1000);
  }
}

component.html

INTERVAL : {{interval | async}} //Displays the interval incrementing each second
FUNCTION : {{myInterval() | async}} //Not working

答案1

得分: 3

如果你尝试

myInterval() {
    console.log('here');
    return interval(1000);
}

你会注意到这个函数每1秒被调用一次。这将每次给你一个新的对象(return interval(1000)),因此仅使用引用是有效的。

为什么会发生这种情况?(由 @C_Ogoo 提供输入)

因为你返回了1秒的间隔,之后由于你在这里使用了插值,触发了变更检测循环。由于这个原因,函数会被再次调用,导致每次都会得到一个新的间隔。

英文:

If you try

myInterval() {
    console.log('here');
    return interval(1000);
}

you will notice that this function is getting called each 1s. That will give you new object every time (return interval(1000)), hence using just reference is working.

Why this is happening ? (With inputs from @C_Ogoo)

As you are returning interval of 1s, after that the change detection cycle kicks in as you have used interpolation here. Due to this the function gets called again and resulting in new interval every time.

答案2

得分: 2

以下是要翻译的内容:

"它被调用并按您的预期工作。

问题是,由于它是一个函数,它将在每次变更检测周期中不断被评估,并返回一个新的间隔引用。

将您的函数的返回值更改为

return interval(1).pipe(tap(n => console.log(n)))

这将使事情变得更清晰。"

英文:

It is invoked and works exactly as you would expect.

the problem is, since its a function, it will constantly get evaluated, and return a new interval reference on each change detection cycle.

change your function's:return value to

return interval(1).pipe(tap(n => console.log(n)))

it will make things much clearer

答案3

得分: 1

每次Angular通过变更检测器刷新页面时,它会检查绑定对象的值/引用,如果有新对象,算法会将新值放入视图中。myInterval()方法在每次变更检测时提供新对象的引用。可能是Angular在加载您的视图时出现了问题。this.interval始终是同一个对象,因此它只加载一次到会话缓存中。

类似的情况是当您将PromiseLike类型放入视图中时,如下所示:

getPromisValue() {
    return Promise.resolve("anything");
}

<p>{{getPromiseValue() | async}}</p>

它始终是相同的值,但新的Promise引用,因此视图会有加载问题。

为了跟踪这种情况,良好的做法是在app.component.ts中注入ngZone并记录onStable可观察对象。

constructor(
    private zone: NgZone
  ) {
    this.zone.onStable.asObservable().subscribe(() => console.log("onStable"));
  }

正如Angular文档所说https://angular.io/api/core/NgZone#onStable:

通知最后一个onMicrotaskEmpty已运行,没有更多微任务,这意味着我们即将放弃VM轮次。此事件仅调用一次。

因此,如果您做错了什么,您将在控制台中看到日志出现太多次。在生产环境中禁用这个。

英文:

Every time angular refreshes page by change detector, it checks values/references of bound objects and if there is new one, algorithm puts new values into view. myInterval() method gives reference for new object on every change detection tick. Probable angular has trouble in loading your view. this.interval is all the time same object, so its loaded only once to session cache.

Similar situation is when you would put a PromiseLike type into view like this:

getPromisValue() {
    return Promise.resolve(&quot;anything&quot;);
}

&lt;p&gt;{{getPromiseValue() | async}}&lt;/p&gt;

its all the time the same value but new promise reference so view will have a trouble to load it.

To track such situations, good practise is to inject ngZone in app.component.ts and log onStable observable.

constructor(
    private zone: NgZone
  ) {
    this.zone.onStable.asObservable().subscribe(() =&gt; console.log(&quot;onStable&quot;));
  }

As angular doc says https://angular.io/api/core/NgZone#onStable it:

> Notifies when the last onMicrotaskEmpty has run and there are no more microtasks, which implies we are about to relinquish VM turn. This event gets called just once.

So if you will do something wrong, you will see in console that log occurs too many times. Disable this on production.

huangapple
  • 本文由 发表于 2020年1月4日 00:11:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/59581766.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定