Search code examples
javascriptmultithreadingeventscallbacksingle-threaded

Understanding JavaScript's single-threaded nature


I've been reading John Resig's "Secrets of a JavaScript Ninja" and it explains that JavaScript is single-threaded. However, I tried testing this and I'm not sure what to take away from here:

// executing this in browser
(function () {
    // throw something into event queue
    setTimeout(function () {
        alert("This will be called back after 1 second.");
    }, 1000);

    // arbitrary loop to take up some time
    for (var i = 0; i < 10000; i += 1) {
        console.log(i);
    }
})();

Maybe I'm not understanding exactly what being single-threaded means, but I thought that the setTimeout callback wouldn't execute until all of the outer anonymous function is complete. However, running this in the browser shows that the callback function gets called while i's are still being outputted onto the console. To me, this seems like there's 2 threads with anonymous function's invokation occupying 1 thread and then the callback using the 2nd thread.

Can someone help un-confuse me?


Solution

  • console.log() is a weird function in some browsers (like Chrome) and is not synchronous itself so you can't really use it to gauge the single threadedness. What you are probably seeing is that the JS engine executes all the console.log() statements and then the setTimeout() runs to show the alert and, in parallel (in some other process that isn't javascript) all the data is being shown in the console.

    Javascript is indeed single threaded. In your example, the setTimeout() callback will not execute until your for loop is done.

    You can illustrate it better like this:

    (function () {
        // throw something into event queue
        setTimeout(function () {
            alert("This will be called back after 1 second.");
        }, 1000);
    
        function now() {
            return new Date().getTime();
        }
        var start = now();
        // loop for 1.2 seconds
        while (now() - start < 1200) {}
        alert("Looping done");
    })();
    

    Working jsFiddle demo: http://jsfiddle.net/jfriend00/3sBTb/