Menztrual
Menztrual

Reputation: 41587

setTimeout with arguments

having a bit of a headache on trying to work this out. What I want to do is have a custom setTimeout with arguments with out having to create a function to pass it. Let me explain by code:

Want to avoid:

function makeTimeout(serial){
  serial.close();
}

setTimeout(makeTimeout(sp.name), 250);

what I want to do is somehow just call a 1 liner by like:

setTimeout(function(arg1){ .... }(argument_value), 250);

Can this be done or can you only pass in a no argument function?

Upvotes: 16

Views: 38514

Answers (4)

N00BEST
N00BEST

Reputation: 23

I had a method that needed a constant timeout setting also having parameters to the final executed function, so I did as follow using anonymous functions:

function checkPageLoaded(checker, callback, nextCallTime) {
    return () => {
        let checkoutLoader = document.querySelector(checker);
        if(checkoutLoader === null)
            callback();
        else
            setTimeout(checkPageLoaded(checker, callback, nextCallTime), nextCallTime);
    }
}

and then just call it as follows:

setTimeout(checkPageLoaded('.loader', reloadPagination, 500), 500);

This way the desired function to be executing with the arguments will be the one defined as an anonymous one.

Upvotes: 0

unsynchronized
unsynchronized

Reputation: 4938

It appears the ability has been added to some browsers pass parameters to setTimeout:

syntax: setTimeout (function (p1,p2) {},1000,p1,p2); (add as many params as you want)

If you want to ensure it works everywhere, you can use the attached code.

Note: If you want to set a timeout immediately after installing it, it's best to use the callback parameter and do it in there

for example

installSwizzledTimeout(function(param1,param2){
    setTimeout(myFunc,200,param1,param2);},param1,param2);
}

This is because it uses a trick to detect if it is needed, by setting a very short timeout and counting the parameters.

window.swizzledSetTimeout = function (fn, ms) {
    if (arguments.length === 2) {
        //console.log("Bypassing swizzledSetTimeout");
        return window.originalSetTimeout(fn, ms);
    } else {
        var args = [];
        for (i = 2; i < arguments.length; i++) {
            args.push(arguments[i])
        };
        //console.log("Setting swizzledSetTimeout for function (",args,") {...} in ",ms," msec");
        var retval = window.originalSetTimeout(function () {
            //console.log("Invoking swizzledSetTimeout for function (",args,") {...}");
            fn.apply(null, args);
        }, ms);
        return retval;
    }
}

function installSwizzledTimeout(cb) {
    var args = [];
    for (i = 1; i < arguments.length; i++) {
        args.push(arguments[i])
    };
    setTimeout(function (arg) {
        //console.log("arguments.length:",arguments.length,window.setTimeout.toString());
        if (arguments.length == 0) {

            function doInstall() {
                //console.log("Installing new setTimeout");
                window.originalSetTimeout = window.setTimeout;
                window.setTimeout = function setTimeout() {
                    return window.swizzledSetTimeout.apply(null, arguments);
                };
                if (cb) {
                    cb.apply(null, args);
                };
            }

            if (window.setTimeout.toString().indexOf("swizzledSetTimeout") < 0) {
                doInstall();
            }
        } else {
            //console.log("existing set time supports arguments ");
            if (cb) {
                cb.apply(null, args);
            };
        }
    }, 0, 1, 2, 3, 4);
}

Upvotes: 3

RobG
RobG

Reputation: 147363

If you don't want to declare a separate function, you can use an immediately invoked function expression and closure, e.g.

// Parameter to use
var bar = 'bar';

// Function to call
function foo(arg) {
  alert(arg);
}

// Go…
setTimeout(
  (function(arg1){
    return function(){
      foo(arg1);
    };
  }(bar)), 2000);

Alternatively, you can use the function constructor:

setTimeout( Function('foo(bar)'), 2000);

Or you can use a string:

setTimeout('foo(bar)', 1000);

which is essentially the same thing. Now wait for howls of "but that's like using eval, and everyone knows eval is evil and a massive security breach — all your firstborn are doomed!"

But seriously, eval (and the Function constructor) are inefficient and can lead to lazy programming, so use another option, such as the first above.

Upvotes: 7

Jo&#227;o Silva
Jo&#227;o Silva

Reputation: 91299

You can pass it an anonymous function that invokes makeTimeout with the given arguments:

setTimeout(function () {
  makeTimeout(sp.name);
}, 250);

There's also an alternative, using bind:

setTimeout(makeTimeout.bind(this, sp.name), 250);

This function, however, is an ECMAScript 5th Edition feature, not yet supported in all major browsers. For compatibility, you can include bind's source, which is available at MDN, allowing you to use it in browsers that don't support it natively.

DEMO.

Upvotes: 24

Related Questions