Reputation: 41587
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
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
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
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
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