何时以及为何在Angular 2中使用'tick'?

duk*_*636 19 angular

我已经看到在Angular 2组件类中使用了以下内容:

setTimeout(()=>{}, 0);
Run Code Online (Sandbox Code Playgroud)

这意味着,在0秒后调用一个空函数.我知道这与Javascript事件模型有关,但完全不了解它.

请使用带有一些代码片段的小型真实示例解释何时以及为何在Angular 2中完成此操作.

Gün*_*uer 12

setTimeout(()=>{}, 0);
Run Code Online (Sandbox Code Playgroud)

导致Angular对整个应用程序运行更改检测,例如ApplicationRef.tick

zone.js修补程序异步API(addEventHandler,, setTimeout...)并在回调完成后运行更改检测.

  • 您也可以在区域外执行(按区域api).但同样,你必须知道这一点.我参加过由Angular团队主持的一些Angular 2聚会,并没有人提到这一点,尽管他们确实讨论了区域是如何成为新的摘要. (3认同)

Ced*_*Ced 5

我会补充一下Gunter的答案,因为它目前很小。

他说 :

setTimeout(()=>{}, 0); 使Angular对整个应用程序运行更改检测

这是因为该setTimeout方法已被猴子修补以通过角度进行拦截,该角度在拦截时触发更改检测。换句话说,每次setTimeout都称为发生更改检测。

可以这样做:

const temp = window.setTimeout;
window.setTimeout = (...args) => {
    temp(...args)
    angular.triggerChangeDetection(); // or w.e they use
}
Run Code Online (Sandbox Code Playgroud)

所以0是使更改检测立即发生,而empty函数是因为我们什么都不做。


Tim*_*zio 3

我记得很久以前就问过这个问题。在一个名为 angular-flexslider 的 github 存储库中得到的回应是,它是$(document).ready(function() {...})).

Angular 在页面加载后操作 DOM。有时,当 CPU 有点忙时,您会看到页面加载后角度表达式会更新。超时函数确保代码在 Angular 处理完文档后运行零毫秒。

我从来没有这样做过,而且现在有了组件生命周期钩子,我无法想象您会再次需要这样做(也就是说,如果您确实需要的话)。但就 Angular 而言,这就是我所看到的原因。我还可以说,我见过很多由工程师编写的 Angular 代码(就他们对 Angular 的了解而言),您对此有很高的信心,但从未见过有人这样做。

此外,它也是确保要运行的代码放置在当前事件循环队列末尾的一种方法。这样做通常是为了性能。我曾经对“无限滚动”列表执行类似以下操作(现在都是 RxJS、Observables 等)。考虑这段代码:

var res = []
function response ( d ) {
  var chunk = data.splice ( 0, 1000 );

  res = res.concat ( chunk.map ( ...do something ) );

  if ( data.length > 0 ) {
    setTimeout ( () => { response ( data ) }, 0 );
  }
}
Run Code Online (Sandbox Code Playgroud)

因为您是response通过setTimeout递归调用来处理块的,所以即使它有 0 间隔,您也是分批进行的,并且每个批次都将在当前作业队列的末尾进行处理(而不是仅仅构建一个堆栈)事件队列中的事件数,这将是阻塞的)。