duke636
duke636

Reputation: 800

When and why to use a 'tick' in Angular 2?

I have seen the following is used in an Angular 2 component class:

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

That means, an empty function is called after 0 seconds. I know this is related to Javascript event model, but do not understand it completely.

Please explain when and why this is done in Angular 2, using a small real world example with some code snippet.

Upvotes: 26

Views: 23116

Answers (3)

Ced
Ced

Reputation: 17397

I'll add on the answer of Gunter as it is small at the moment.

He says :

setTimeout(()=>{}, 0); Causes Angular to run change detection for the whole application

This is because the setTimeout method has been monkey patched to be intercepted by angular which upon interception triggers change detection. In other words everytime setTimeout is called a change detection happens.

this could be done like this:

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

So the 0 is to make the change detection happen immediately and the empty function is because we don't want to do anything.

Upvotes: 8

Tim Consolazio
Tim Consolazio

Reputation: 4888

I remember asking this question quite some time ago. The response, which was in a github repo called angular-flexslider, was that it's sort of a component-level substitute for $(document).ready(function() {...})).

Angular manipulates the DOM after the page has loaded. You can sometimes see angular expressions update after the pages have loaded when the CPU is a little busy. The timeout function ensures that the code is run zero milliseconds after angular has finished processing the document.

I've never had to do it, and these days with the component lifecycle hooks I can't imagine you'd ever need to again (that is, if you really ever did need to). But in Angular terms, that's the reason I've seen. I can also say that I have seen a lot of Angular code written by engineers you'd have a very high degree of confidence in (as far as their knowledge of Angular) and never once seen anybody do this.

Also, it is a way of making sure that the code you want to run is placed at the end of the current event loop queue. It's often done for performance. I used to do something like the following for "infinite scrolling" lists (now it's all RxJS, Observables, etc). Consider this code:

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 );
  }
}

Because you are recursively calling response via the setTimeout to process chunks, even though it has a 0 interval, you are doing it in batches, and each of those batches will be processed at the end of the current job queue (instead of just building up a stack of events in the event queue, which would be blocking).

Upvotes: 3

Günter Zöchbauer
Günter Zöchbauer

Reputation: 657937

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

Causes Angular to run change detection for the whole application, like ApplicationRef.tick

zone.js patches async APIs (addEventHandler, setTimeout, ...) and runs change detection after a callback was completed.

Upvotes: 16

Related Questions