views:

38

answers:

3

Hi there,

I've got a sequence of Javascript function calls in a function I have defined to be executed when a web doc is ready. I expected them to be executed in sequence, as one ends the next begins, but the behaviour I see doesn't match up with that.

Additionally there is manipulation of the graphical components going on in between the calls (for example, I add in a checkpoint time to draw on a div on the page inbetween each of the mentioned calls) but those redraws aren't happening in sequence... they all happen at once.

I'm a bit of a n00b with the whole javascript-in-the-browser thing, is there an obvious mistake I'm making, or a good resource to go find out how to do this stuff?


Update - sample

// called onReady()
function init() {
    doFirstThing();
    updateDisplayForFirstThing();
    doSecondThingWithAjaxCall();
    updateDisplayForSecondThing();
    ...
    reportAllLoaded();
}
+1  A: 

IE won't update the display until the current script is finished running. If you want to redraw in the middle of a sequence of events, you'll have to break your script up using timeouts.

If you post some code we can help refactor it.

edit: here's a general pattern to follow.

function init() { 
    doFirstThing(); 
    updateDisplayForFirstThing(); 
} 

function updateDisplayForFirstThing() {
    // existing code
    ... 

    // prepare next sequence
    var nextFn = function() {
        // does this method run async? if so you'll have to 
        // call updateDisplayForSecondThing as a callback method for the 
        // ajax call rather than calling it inline here.
        doSecondThingWithAjaxCall(); 

        updateDisplayForSecondThing();     
    }

    setTimeout(nextFn, 0);
}

function updateDisplayForSecondThing() {
    // existing code
    ... 

    // prepare next sequence
    var nextFn = function() {
         // continue the pattern 
         // or if you're done call the last method
         reportAllLoaded(); 
    }
    setTimeout(nextFn, 0);
}
lincolnk
Yes, fantastic. Don't suppose you can point me at a good resource that explains the difference between using callbacks and procedural code?
Brabster
@Brabster procedural code is when you directly call functions one after another. a callback is function that you pass as a parameter to some other method, which will invoke it at some later time. it may be called synchronously (procedurally, inline) or it may be deferred with a timeout or the like. waiting for an ajax call to complete before doing the next step is like using a timeout, it's just that they depend on different mechanisms to delay the action. hwoever both of them allow the user to interact with the client in the meantime.
lincolnk
+1  A: 

This can be fixed for many cases by using callbacks, especially with AJAX calls -- for example:

function doFirstThing(fn){
  // doing stuff
  if(typeof fn == 'function') fn();
}

function updateDisplayForFirstThing(){
  // doing other stuff
}

function init(){
  doFirstThing(updateDisplayForFirstThing);
}

Another option is to use return values:

function doFirstThing(fn){
  // doing stuff
  if(x) return true;
  else return false;
}

function updateDisplayForFirstThing(){
  // doing other stuff
  return true;
}

function init(){
  if(doFirstThing()){ updateDisplayForFirstThing(); }
}

setting timeouts to step through your code is not really a good way to fix this problem because you'd have to set your timeouts for the maximum length of time each piece of code could possibly take to execute.

However, you may still sometimes need to use a setTimeout to ensure the DOM has properly updated after certain actions.

Daniel Mendel
+1  A: 

If you end up deciding that you would like some JavaScript threading, check out the still being drafted Web Workers API. Browser support is hit and miss though the API is implemented in most modern web browsers.

Question: exactly how did you go about determining when the "doc is ready"? The DOMContentLoaded event isn't supported in IE I'm fairly certain... if you're in need of waiting for your document to load in its entirety you could use something like this:

var onReady = function(callback) {
    if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", callback, false);
        return true;
    } else if (document.attachEvent) {
        var DOMContentLoaded = function() {
            if (document.readyState === "complete") {
                document.detachEvent("onreadystatechange", DOMContentLoaded);
                onReady();
            }
        };
        return true;
    }
};

Then of course you'll need to develop a setTimeout testing for some flags state indicating the page is loaded upon completion before continuing the execution of the rest of your code... that or any number of other methods...

Or you could just include the script at the bottom of your body...

I'm just rambling though until you have some code to show us?

Xaxis