7

I'm writing two scripts in an web environment where I don't have control over the order in which they are loaded. Let's say the two scripts are called MyUtil and DoSomething.

MyUtil contains utilities that I will bind to the window object using window.myUtil = myUtil. I'm then going to call methods of myUtil from within DoSomething.

If MyUtil is loaded first, everything will work. If it's loaded second, window.myUtil will be undefined.

How can I modify the code in DoSomething (and/or MyUtil) to wait until window.myUtil exists before DoSomething executes its code?

NB: I'm using jQuery 1.2.3.

2
  • Do you have access to the code that dynamically loads MyUtil? If so, you can use jQuery.getScript() to load it and then call DoSomething in the success callback. Commented Jun 3, 2011 at 13:41
  • @Rob I could go that route, but in the environment I'm in, I think that would introduce more maintenance in the long term on my part. Commented Jun 3, 2011 at 13:47

7 Answers 7

8

jQuery.Deferred objects provide a very elegant way to do this (I know you're not using jQuery 1.5: I'm just giving you a reason to upgrade ;-):

Assuming we have two scripts co-operating like the following:

// defines utilities    
var util = util || { loaded: $.Deferred() };
(function(){
    $.extend(util, {
        msg: "Hello!"
    });
    util.loaded.resolve();
})();

... and:

// uses them
var util = util || { loaded: $.Deferred() };
util.loaded.then(function(){
    alert(util.msg);
});

... the alert will always fire after the first script has had a chance to define it's utilities no matter the order they load in. This has advantages over the setTimeout and event based approaches in that it's easier to have multiple dependencies (using $.when), doesn't use polling, and you don't have to worry about handling the order-of-loading explicitly.

The only thing that's kind of gross is that all of the modules have to include:

var util = util || { loaded: $.Deferred() };

... and $.extend() it to make sure that they use the same deferred.

Sign up to request clarification or add additional context in comments.

2 Comments

+1 This is excellent. I'm using RSVP and just plugged a deferred into my module without having to use $.extend.
@Aaron Could you please explain the advantage of using a self-invoking function and $.extend() vs util.msg = "Hello!"; util.loaded.resolve();
4

Wait Until myUtil is Available

You could set a timer using window.setInterval() to wait until window.myUtil has been set before attempting to use it.

Example

Example: http://jsfiddle.net/CtJ8A/1/

Simulating a situation where window.myUtil is added after the script that requires it has been loaded:

window.setTimeout((function(){
    window.myUtil = { 
        utility: function(){ alert('utility has great utility!'); }   
    };
}), 5000);

Elsewhere in your page:

// Declaration of function that requires window.myUtil
var doSomething = function() {
     window.myUtil.utility();   
}

/* 
 * Timer that checks for myUtil every 100 milliseconds 
 * When myUtil does exist, the timer is cleared, and doSomething() is called.
 *
 * Alternatively, one could put this timer inside doSomething().
 */
var timer = window.setInterval(function(){
        if (window.myUtil != undefined) {
            window.clearInterval(timer);
            doSomething();
        }
    }, 100);

Comments

2

I ended up using a trigger in MyUtil that I check for in DoSomething. This worked perfectly.

At the end of MyUtil, I added:

$(document).trigger('myUtilLoaded');

At the end of DoSomething, I added:

if (!(window.myUtil))
{
  $(document).bind('myUtilLoaded', function(e) {
    doSomething();
  });
}
else
{
  doSomething();
}

2 Comments

what if myutil gets loaded first, myUtilLoaded will trigger but nothing will be bound to it
@james good point. Updated to check for the existence of myUtil first.
1

You could use the load event

$('body').load(function() {
    window.myUtil.utility();        
});

4 Comments

He doesn't know when 'myUtil' will be added.
Yeah, $(document).ready() was the first thing I tried and that didn't work.
I figured he just wasn't sure which order the script files would be included in the original HTML. So waiting for the load event should guarantee that all the script files have been downloaded. If the script files are loaded dynamically this wouldn't work.
I believe the script files are loaded dynamically
0

Would something like this work?

 function function1(callback){
        var params={
            type: "POST",
            url: "./ajax/doSomethingSlow.php",
            data: "",
            success: function(msg){
                callback(msg);
            },
            error: function(){
                callback('');
            }
        };
        var result=$.ajax(params).responseText;
    }




function1(function(){
   //call function2 here:
   function2();
});

1 Comment

While that might work from a technical perspective, I really don't want to use artificial timing games to get this to work.
0

You could use dynamic loading to load the javascript, but if you also arent in control of where the script located then i suppose this could be an issue as well.

Anyhow in do something you would basiically pull down the script via ajax or use a document.write to insert a new script tag:

function doSomething(){
  if(!window.myUtil){
    // method of choice for loading script
    doSomething();
  }
  else {
    // normal logic for doSomething
  }
}

Then in your util you would need to modify it so it checks for an existing window.myUtil before assigning it. How that would need to look depends on how my utl operates - whether its an object instance or jsut a a literal collection of static functions.

See this link for some methods to actually load the script source.

Comments

0

You can test for window.myUtil and if it's undefined, deal with it. That might mean using setInterval or setTimeout to poll for its existence and when it's found, proceed.

You can also wait for the load event, but that might be too late.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.