window.setTimeout (or, Don’t Wait for Fat Inits)

Because Javascript is a lambda-based language that’s designed to be compiled and run within a browser, it has a few unique architectural features that differentiate it from its more traditional C-style cousins. In particular, there’s no sleep function in Javascript.

Why setTimeout instead of sleep

While Javascript is downloading and running, everything on the page stops. That’s right, everything. If a script doesn’t finish up within a certain amount of time, then the user gets that annoying alert that says, “A script on this page is taking a long time to complete.” The browser shoots your operation in the head, and you look like a n00b.

So, since you’re making the user wait around for your script, it’s only fair that the browser isn’t going to give you a way to sit around doing nothing. It says, “I’ll wait for you to do your business, but hurry up, cuz there’s other stuff to do!”

Of course, there are many scenarios when you want something to happen in a little while. So, the Javascript language provides two functions to help us do this: setTimeout and clearTimeout. setTimeout takes two arguments. The first is either a string to be evaled or a function to be run. The second is a number of milliseconds. (Since eval is evil, and the function route allows for closures, I tend to send it a function instead of a string.)

It’s worth noting that, in this crazy world of browser quirks, the second argument isn’t really exact. It’s more of a suggestion to the browser. It won’t run any sooner than you suggest, but it might run a few milliseconds later. In my experience, depending on the machine, browser, and other stuff on the page, setTimeout fires between 0 and 50 ms later than you tell it to. Bigger functions tend to take longer to fire.

Ok, so what’s a “Fat Init”?

You’ve probably seen this before. You write a bit of brilliant Javascript that flawlessly implements some beautifully intuitive behavior. And, while it’s blazingly fast in action, it requires you to set up a huge object with a bunch of references to DOM nodes, and you have to join an array of 10,000 strings into the innerHTML of some DIV. So, you load up the page, and it gets down to your module, where it hangs for 3 seconds, and then loads the rest of the page.

That’s the Fat Init problem. Your code is slick, but the initialization takes for damn ever. Those three seconds probably wouldn’t be missed, except for the fact that it’s three seconds where the user can’t do anything. Thats right—no back button, no downloading images, no refresh, nothing.

How can setTimeout help?

I know what you’re thinking—”My init function is taking long enough as it is, why would I want to delay it further?”

Well, here’s the tricky part: setTimeout isn’t just a sleep, it’s more like a fork and a sleep in one. That is, it makes a function run asynchronously. It forks the browser’s script engine into another process, and runs the code side-by-side with anything else that might be happening.

So, if you send 0 as the second argument, you get a fork for free. You’re essentially telling the browser, “Run this as soon as you can, but don’t wait around for it to finish.” So, you go from this:

doSomething(); // takes forever!

to

window.setTimeout(doSomething,0); // still takes forever, but doesn't freeze the browser

Of course, if you have other code that’s dependent on doSomething, then you have to structure things a bit differently. The next line of code after your setTimeout will fire immediately, and most likely before doSomething is called. Sometimes something like this can help:

Instead of:
var doSomething = function() {
  // ... create 10000 table cells or whatever
};
var doSomethingElse = function() {
  // ... do something simple that needs those 10000 table cells to be there.
};
doSomething(); // takes forever!
doSomethingElse(); // goes fast, but depends on doSomething

You can instead chain the functions together:
var doSomething = function() {
  // ... create 10000 table cells or whatever
  doSomethingElse(); // goes fast, but depends on doSomething
};
var doSomethingElse = function() {
  // ... do something simple that needs those 10000 table cells to be there.
};
window.setTimeout(doSomething,0); // fork you

Or just use a lambda, which is even faster for small lambdas:
var doSomething = function() {
  // ... create 10000 table cells or whatever
};
var doSomethingElse = function() {
  // ... do something simple that needs those 10000 table cells to be there.
};
window.setTimeout(function(){
    doSomething(); // takes forever!
    doSomethingElse(); // goes fast, but depends on doSomething
  },0); // fork the lambda

One Response to “window.setTimeout (or, Don’t Wait for Fat Inits)”

  1. On November 21st, 2006 at 23:39:37, Schlueterica » asynchBatch Javascript Function Said:

    [...] A while ago, I wrote about using setTimeout with a 0 timeout in order to asynchronously perform certain actions, so that the browser’s UI thread will be returned while your fat init function runs in the background. [...]

Leave a Reply

Comments are moderated like crazy using a variety of plugins. There is a very high likelihood that your comment won't show up right away, especially if you have never commented here before, but it was not deleted.

Please be patient, and do not post your comment more than once. It will show up once it is approved.

You must be logged in to post a comment.