Reputation: 800
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
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
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
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