Paul Marsden
Paul Marsden

Reputation: 151

I need a generic javascript "wait for function to be available"

I have found this excellent snippet Make my userscript wait for other scripts to load that shows me how to wait for a function to be available before calling it.

Currently I have this local code in my script which I have put together which works for me

waitForFnc();

function waitForFnc() {
    if (typeof Portal.Management_Init == "undefined") {
        window.setTimeout(waitForFnc, 50);
    }
    else {
        Portal.Management_Init();
    }
}

However, I would like to write a generic version of 'waitForFnc' as I need to do the same thing in several places. Something like

waitForFnc(Portal.Management_Init);

function waitForFnc(fnc) {
    if (typeof fnc == "undefined") {
        window.setTimeout(waitForFnc(fnc), 50);
    }
    else {
       fnc();
    }
}

where I pass the name of the function in which is called when it becomes available. The above code does not work but I am unsure as to how to resolve it.

Regards Paul

Upvotes: 5

Views: 1996

Answers (4)

Yusuf X
Yusuf X

Reputation: 14633

Depending on what you're loading, you might be able to leverage require.js to take care of this for you; that's basically what it's for: http://requirejs.org/docs/why.html#9

Upvotes: 0

jordancpaul
jordancpaul

Reputation: 2964

There are some potential problems with what you are trying to do. If you call waitForFnc() before Portal is even defined, you will get a null property access exception. If you are trying for a truly generic solution, you will probably have to use eval() *gasp*

While we're at it, let's add support for passing arguments to the function we're waiting on.

function waitForFn(fnName, args){
    var fn;
    try{
        eval("fn = " + fnName);
        if(fn){
            fn.apply(null, args);
        }else{
            setTimeout(function(){waitForFn(fnName, args);}, 50);
        }
    }catch(e){
        setTimeout(function(){waitForFn(fnName, args);}, 50);
    }
}

waitForFn("Portal.Management_Init", [arg0, arg1]);

Upvotes: 5

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340983

In your code replace:

window.setTimeout(waitForFnc(fnc), 50);

with closure:

window.setTimeout(function() {waitForFnc(fnc)}, 50);

But may I ask why do you need such a weird code? I would rather expect to have an API allowing to register some callback:

Portal.onManagementInitAvailable(fn);

Upvotes: 0

bezmax
bezmax

Reputation: 26142

Basically, when this line of code is executed: window.setTimeout(waitForFnc(fnc), 50);, the "waitForFnc" is evaluated before the timeout is set. While you need to pass the calling statement as a parameter.

Here's how you do that:

window.setTimeout(function() {waitForFnc(fnc);}, 50);

What this does, it defines a function, the same way as if you'd write it into the variable:

var myFunc = function() {
    waitForFnc(fnc);
};

This function is not yet executed, it is only defined. Then you pass it into the "setTimeout":

window.setTimeout(myFunc, 50);

Which makes the "setTimeout" to execute that function after 50msec. And when it does, it will call waitForFnc(fnc).

Upvotes: 3

Related Questions