简体   繁体   English

Angular setTimeout 性能不佳

[英]Angular setTimeout Poor Performance

I have a component that I need to re-render every time with different @input variables because I have some logic implemented in ngOnInit() .我有一个组件,每次都需要使用不同的@input变量重新渲染,因为我在ngOnInit()中实现了一些逻辑。 I am doing this by using following method in parent component with showSettings being used to hide and then show the component (with new inputs) after 100ms delay.我通过在父组件中使用以下方法来执行此操作,其中showSettings用于隐藏,然后在100ms延迟后显示组件(带有新输入)。

private _reloadSettings() {
    this.showSettings = false;
    let a = performance.now();
    setTimeout(() => {
         this.showSettings = true;
         console.log(performance.now() - a);
     }, 100);
    }

Everything is working fine except that the re-render takes so much time than expected ie it should be around 100ms (or a little over) but actually I am getting like 8000ms to 10000ms , and with each re-render it gets worst.一切工作正常,除了重新渲染花费的时间比预期的要长,即它应该在 100 毫秒左右(或稍微多一点),但实际上我正在变得像8000ms10000ms ,并且每次重新渲染都会变得最糟糕。

In other parts of your application, you are doing too much work.在您的应用程序的其他部分,您正在做太多的工作。

We cannot solve your problem in this case.在这种情况下,我们无法解决您的问题。 I would go about looking into angular change detection .我会 go 关于调查angular 变化检测

Other than that, I will show you few things to look for in your codebase:除此之外,我将向您展示在您的代码库中要查找的一些内容:

ChangeDetection变化检测

You could switch from ChangeDetection.Default to ChangeDetection.OnPush .您可以从ChangeDetection.Default切换到ChangeDetection.OnPush This may break parts of your app, but if you would fix those, you will get a big performance boost for all app-wide actions as setTimeout is.这可能会破坏您的应用程序的某些部分,但如果您修复这些问题,您将获得与setTimeout一样的所有应用程序范围的操作的巨大性能提升。

In the example above, you are listening to service observable, it might be anything在上面的例子中,你正在监听 service observable,它可能是任何东西

Leaking subscription泄露订阅

constructor(myService) {
  myService.data.subscribe(data => {
    this.array = data.array;
  });
}

The code above is bad, the subscription is never removed, meaning the browser cannot remove the component from memory AND the code inside subscribe method runs every time.上面的代码很糟糕,订阅永远不会被删除,这意味着浏览器无法从memory中删除组件,并且subscribe方法中的代码每次都会运行。 It is fine in this case, but if you were to do some computation inside, it could get bad quickly.在这种情况下很好,但如果你要在内部进行一些计算,它可能会很快变坏。

You can fix it by:您可以通过以下方式修复它:

  1. Subscribing to first emission only.仅订阅首次发射。
myService.data.pipe(
  take(1),
).subscribe(data => {
  this.array = data.array;
});
  1. Replacing it with piped observable.用管道的 observable 替换它。 This will keep it reactive, but the angular will这将使其保持反应性,但 angular 将
this.array$ = myService.data.pipe(
  map(data => data.array),
  // Uncomment next line, if the observable is used multiple time
  // shareReply({ ... }), // 
)

Try using queueMicrotask instead of setTimeOut.尝试使用 queueMicrotask 而不是 setTimeOut。

queueMicrotask(() => {
     this.showSettings = true;
     console.log(performance.now() - a);
 });

SetTimeout is a macro task. SetTimeout 是一个宏任务。 The call back function provided in setTimeout will be loaded into the call back queue(aka MacroTaskQueue). setTimeout 中提供的回调 function 将被加载到回调队列(又名 MacroTaskQueue)中。 It waits until the call stack is empty.它一直等到调用堆栈为空。

The micro task also has similar behavior.微任务也有类似的行为。 But, the microtask gets higher priority, and hence it runs prior to the macro task queue.但是,微任务获得更高的优先级,因此它在宏任务队列之前运行。

read more about it here 在此处阅读更多信息

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

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