SetTimeout

SetTimeout can appear to provide concurrent code execution. While SetTimeout is not part of the ECMA-262 language specification, it is still implemented within a single threaded environment.

Here is a test I performed to try and understand whats going on.

function() test1{
window.setTimeout( function(){alert('TimeOut function');},100);
for(var i=0; i<=10000000;i++) { if(i==10000000) {alert('long running process');} }} window.onload = Test1;
In this example, the alert 'long running process' always executes before 'TimeOut function'.

From this test we can conclude that the anonymous function is not guaranteed to be executed when the time period passed to the setTimeout method has elapsed.

So whats happening?

As I pointed out previously, JavaScript is single threaded and as such can only ever execute one piece of code. This means that if an asynchronous event such as a mouse click or a setTimeout call to anonymous function, occurs during the excution of a code block (not necessarily an atomic call), the event is queued.

At the next available point during execution the queue will be queried and the next atomic code block executed.

However, if we remove the "if" statement from the loop in the test we get a different result.
function() test2 {
window.setTimeout( function(){alert('TimeOut function');},100);
for(var i=0; i<1000000;i++){alert(i);}}>

window.onload = test2;
The "TimeOut function" can be alerted before, during and after the alerts within the loop, for example:
  • 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • setTimeOutCalled
  • 6
  • 7
  • 8
  • 9
  • ...
Does this contradict our previous conclusions? No.

The javascript "alert" method is not responsible for creating the popup box that we see. The browsers UI thread does this. Which means that we have two threads, the javascript (containing our async queue) and the browsers thread for rendering UI. So, we cant guarantee the order we see the alerts, is the order that the javascript executes the alert statement

So, to truely understand whats going on, we need to try to remove interactions with the UI thread.

We will place our "alerts" into an array and render (note that I have used attached an add method to the Array constructor to help with manipulating arrays).
var var messages = [];
function test2_Revisited() {
window.setTimeout( function(){Array.add(messages,"setTimeOutCalled");},100);
for(var i=0; i<1000000;i++) {Array.add(messages,i);}}
window.onload = test2_Revisited;
  • 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • ...
  • 999999
  • setTimeOutCalled
Conslusions
  1. We cannot guarantee that the delay requested in a setTimeout will be honoured.
  2. The seperate UI thread means that alerts and console.logs calls from javascript are not synchronised with the user experience.
For more information  see this excellent article written by Jphn Resig 

Posted in Labels: , , , , |

0 comments: