【问题标题】:Why does setTimeout() make my app laggy, but Rxjs timer().subscribe(...) does not?为什么 setTimeout() 使我的应用程序滞后,而 Rxjs timer().subscribe(...) 却没有?
【发布时间】:2020-06-17 08:36:54
【问题描述】:

我有一个组件,它以 100 毫秒的间隔“延迟加载”一些 cmets。

当我使用 setTimeout 时,它真的很滞后。

组件

<div *ngFor="let post of posts">
   <app-post [post]="post" ></app-post>
</div>

这使我的应用程序滞后(平均 fps 14,空闲时间 51100 毫秒):

while(this.postService.hasPosts()){
  setTimeout(()=> {
   this.posts.push(this.postService.next(10));
  },100);
}

这使我的应用程序流畅(平均 fps 35,空闲时间 40800 毫秒)

while(this.postService.hasPosts()){
  timer(100).subscribe(()=> {
    this.posts.push(this.postService.next(10));
  });
}

有什么解释,为什么 rxjs 计时器工作得更好?

我用 Firefox 进行了运行时分析。 在第一个示例中,帧速率降至 14 fps 在另一个示例中,35 fps。

甚至空闲时间也减少了 20%。

这种方法更流畅(平均 fps 45,空闲时间 13500ms):

interval(100).pipe(takeWhile(this.postService.hasPosts()).subscribe(()=> {
    this.posts.push(this.postService.next(10));
  });
}

【问题讨论】:

    标签: javascript angular typescript rxjs


    【解决方案1】:

    您的最后一个解决方案是唯一正确的解决方案。

    其他两种解决方案不应像您预期的那样起作用。实际上,这应该会导致无限循环。

    这是因为 JavaScript 的 eventloop 是如何工作的。下图是 JavaScript 运行时的模型(图片来自here):

    与我们相关的部分是stackqueue。 JavaScript 运行时处理queue 上的消息。每条消息都与一个函数相关联,该函数在处理消息时被调用。

    对于堆栈,每个函数调用都会在堆栈上创建一个框架,其中包含函数参数和局部变量。如果一个函数调用另一个函数,则会将一个新帧推入堆栈顶部。当函数返回时,栈顶帧被弹出。

    现在如果堆栈为空,JavaScript 运行时将处理queue(最旧的)上的下一条消息。

    如果您使用 setTimeout(() =&gt; doSomething(),100),则 doSomething() 函数会在 100 毫秒后添加到队列中。这就是为什么 100 毫秒不是保证时间而是最小时间的原因。因此,您的 doSomething method 只有在堆栈为空且队列中没有其他内容时才会被调用。

    但是当您在 while 循环中进行迭代并且您的条件取决于 setTimeout 中的代码时,您创建了一个无限循环,因为堆栈不会变空,因此您的 this.posts.push(this.postService.next(10)); 代码将永远不会被调用。

    对于 RxJS 实现也是如此。他们使用调度程序来处理时间。 RxJS 中有不同的内部调度器实现,但正如我们在intervaltimer 的实现中看到的那样,如果我们不指定调度器,则默认的调度器是 asyncScheduler。 asyncScheduler 调度与setInterval 一起工作,其工作方式类似于上面提到的setTimeout,并将另一条消息推送到队列中。

    我用 while 循环尝试了你的两种解决方案,实际上第一个完全冻结了我的浏览器,而第二个超级滞后,但可以在 while 循环内向控制台输出一些东西。我实际上不知道为什么第二个性能更高一些,但是两者都不是您真正想要的。您已经提出了一个很好的解决方案,我希望这个答案可以帮助您理解为什么第一个解决方案表现如此糟糕。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-24
      • 2019-01-31
      • 2015-09-17
      • 2016-06-19
      • 1970-01-01
      • 2016-06-22
      • 2018-11-11
      • 2017-07-09
      相关资源
      最近更新 更多