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

时间:2017-01-15 09:50:54

标签: angular

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

setTimeout(()=>{}, 0);

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

请使用一些现实示例和一些代码段,解释Angular 2中何时以及为何进行此操作。

3 个答案:

答案 0 :(得分:10)

setTimeout(()=>{}, 0);

使Angular对整个应用程序运行更改检测,例如typedefs

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

答案 1 :(得分:2)

我现在补充一下Gunter的答案,因为它现在很小。

他说:

  

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

这是因为setTimeout方法已被猴子修补以被截取角度,在拦截时触发更改检测。换句话说,每次调用setTimeout时都会发生变化检测。

这可以这样做:

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

所以0是让变化检测立即发生而空函数是因为我们不想做任何事情。

答案 2 :(得分:1)

我记得很久以前就问过这个问题了。响应是在一个名为angular-flexslider的github repo中,它是$(document).ready(function() {...}))的组件级替代品。

  

Angular在页面加载后操作DOM。当CPU有点繁忙时,有时可以在页面加载后看到角度表达式更新。超时功能可确保在角度处理完文档后零代码运行代码。

我从来没有这样做过,现在有了组件生命周期钩子,我无法想象你再次需要(也就是说,如果你真的需要)。但从角度来看,这就是我见过的原因。我还可以说我已经看到很多由工程师编写的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 );
  }
}

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