Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wanting pattern for best way to pass function parameters into setTimeout call in JavaScript

I'm struggling with the best way to pass all the parameters passed into a function through to the function in setTimeout. That is, in my example below, I pass one parameter, but it seems to me as this gets more complex it gets ugly (multiple parameters). I'm hoping for a clean pattern to do this since I do it a lot.

onSessionTimeComboChange: function (combo, newValue, oldValue, eOpts) {
    var me = this;
    me.newValue = newValue;
    setTimeout(function () {
        var x = me.newValue;
        debugger;
    }, 100);
}
like image 910
Peter Kellner Avatar asked Feb 16 '23 09:02

Peter Kellner


2 Answers

The reason you don't have access to the main function variables in the callback is that the code executed by setTimeout() is run in a separate execution context to the function from which it was called. In simpler terms, this is not the same in the callback.

If you don't want to use Javascript libraries that provide functions to bind a callback to a context (see jQuery.proxy and underscore.bind), you would have to write your own non-native setTimeout function to fix this.

Here is the solution proposed in the web api docs (See section The "this" problem):

window.setTimeout = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) {
  var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2);
  return __nativeST__(vCallback instanceof Function ? function () {
    vCallback.apply(oThis, aArgs);
  } : vCallback, nDelay);
};

If you don't want to go that far, an improvement to your code would be to pass the arguments to the callback as parameters of setTimeout:

var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);

Check the JavaScript web api for more details.

So in your example, you could just write something like:

setTimeout(function (x) {
    debugger;
}, 100, newValue);
like image 66
edsioufi Avatar answered Feb 17 '23 22:02

edsioufi


Javascript supports closures so you can indeed pass any parameters you need to any callback without much effort:

function bar(x, y, z) {
    console.log([x, y, z]);
}

for (var i=0; i<5; i++) {
    (function(x, y, z){
        setTimeout(function(){bar(x, y, z);}, i*1000+1000);
     })(i, i*2, i*3);
}

The only tricky part is that you cannot just say

setTimeout(function(){bar(i, i*2, i*3)}, i*1000+1000);

because the closure captures the variables (not the current values), so all the registered functions would actually use the same i value in this case.

like image 38
6502 Avatar answered Feb 17 '23 23:02

6502