1

I am working on a simple higher-order function, delay, that will invoke a function parameter, func, and then delay by an amount of time passed in as wait. I have read other answers about where to put in parameters, but none of the answers I found addressed exactly what I need to learn: where and how should I allow for the parameters that may or may not be passed to func?

Original instructions: "Invokes func after wait milliseconds. Any additional arguments are provided to func when it is invoked."

Here's the basic start:

function delay(func, wait) {
    setInterval(func, wait);
}

Another answer on SO states that an anonymous function can be used to wrap the func parameter so that the parameters can be passed in there, but I haven't had any success building that yet.

Guidance is greatly appreciated.

gator
  • 15
  • 1
  • 8

6 Answers6

1

I think the correct way to model it is to acknowledge delays are only side effects and should not have parameters. The delay should be just the delay and that's it.

You might also want to use promises which are the new(ish) standard language way to perform signular asynchronous actions:

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

See this question and answer about what the new Promise part does and what a promise API looks like.

Then, you can use the delay separately from the function call:

delay(1000).then(fn);
delay(1000).then(() => fn(arg1, arg2, arg3));

And so on.

If you want to keep using callbacks

setTimeout actually already does what you're asking for, setTimeout(fn, 1000) is the easy way to invoke a timeout but you can actually pass additional parameters to the function after the delay amount and the function will be called with them.

Community
  • 1
  • 1
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
1

It sounds like you need to make use of the arguments pseudo-array, and Function#apply:

function delay(func, wait) {
  // get all arguments after the first two
  var args = Array.prototype.slice.call(arguments, 2);

  setTimeout(function() {
    func.apply(null, args);
  }, wait);
}

Example:

function delay(func, wait) {
  var args = Array.prototype.slice.call(arguments, 2);

  setTimeout(function() {
    func.apply(null, args);
  }, wait);
}

function outputPerson(firstName, lastName) {
    console.log("Hello, " + firstName + " " + lastName);
}

delay(outputPerson, 3000, "John", "Doe");

Edit: As Patrick Evans and I point out in the comments setTimeout already provides the functionality being described here (as long as you're not using IE <10). So you could even define your delay function like this:

var delay = setTimeout;
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • Since all arguments after the delay amount get passed as arguments to the passed function, you could just do `setTimeout.apply(null,[].slice.call(arguments))`, or just `delay = setTimeout` all equates to the same behavior... – Patrick Evans May 28 '16 at 17:38
0

May be something link this:

function delay(func, wait,funcArguments) {
    setInterval(function() {
        funcArguments = funcArguments  || [];
        func.call(null, funcArguments);
    }, wait);
}

funcArguments is array with arguments.

Georgi Naumov
  • 4,160
  • 4
  • 40
  • 62
0

Usually in libraries they name it debounce and you can simply implement it like:

function debounce(func, wait=0,args=[]) {
    setTimeout(function() {
        func.call({}, args);
    }, wait);
}

But a correct implementation, as lodash's has here, is much more complex.

Avraam Mavridis
  • 8,698
  • 19
  • 79
  • 133
0

You can just add the parameter for setInterval

var intervalID = window.setInterval(func, delay[, param1, param2, ...]);

function delay(func, wait, param) {
    setInterval(func, wait, param);
}


function hello(x) {
    var p = document.createElement('p');
    p.innerHTML = 'Hello ' + x + '!';
    document.body.appendChild(p);
}

delay(hello, 1000, 'world');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

This is simple solution:

function delay(func, wait, ...param) {
  setTimeout(function(){func(param);}, wait);
}
function doit(a){console.log(a);}

delay(doit,500,'test1','test2');
//['test1','test2']
Alex Kudryashev
  • 9,120
  • 3
  • 27
  • 36