Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combined delayed function calls in Javascript

I am not quite sure what the technical term for this is. I have a GUI with interactive graphics. After the user has interacted with the GUI, I need to perform some CPU intensive action. However, user input is very frequent, so I only want to call the function after e.g. 1000ms of no userinput. Below the pattern that I use:

scheduler = (function(){
    var timer;
    function exec(call, delay){
        clearTimeout(timer);
        timer = setTimeout(call, delay);
    };
    return exec;
})()

I.e. if the 3 calls to scheduler are done right after each other, only the final one will actually be executed:

scheduler(function(){alert('foo')}, 1000);
scheduler(function(){alert('bar')}, 1000);
scheduler(function(){alert('zoo')}, 1000);

It seems to work, but it feels a bit hacky I am a little worried about any caveats of Javascript setTimeout, especially the scoping problems. Does this seem like a reliable pattern I could use on a larger scale? Will the inline function that I pass to scheduler be able to lookup all objects in its lexical scope as usual, when it is called by settimeout? What about if I have several of these scheduler instances? Could they interfere with each other? Is there an alternative way of accomplishing this?

like image 283
Jeroen Ooms Avatar asked Dec 21 '12 21:12

Jeroen Ooms


People also ask

How do you delay a function in JavaScript?

To delay a function call, use setTimeout() function. functionname − The function name for the function to be executed. milliseconds − The number of milliseconds. arg1, arg2, arg3 − These are the arguments passed to the function.

How can we delay calling a function after 5 seconds?

How do I delay a function call for 5 seconds? A setTimeout is a native JavaScript function, which calls a function or executes a code snippet after a specified delay (in milliseconds). A setTimeout accepts a reference to a function as the first argument. Alert messages will pop up after 5 seconds automatically.

How do you call a function after a delay?

To call a jQuery function after a certain delay, use the siteTimeout() method. Here, jQuery fadeOut() function is called after some seconds.

How do you wait a couple of seconds in JavaScript?

To delay a function execution in JavaScript by 1 second, wrap a promise execution inside a function and wrap the Promise's resolve() in a setTimeout() as shown below. setTimeout() accepts time in milliseconds, so setTimeout(fn, 1000) tells JavaScript to call fn after 1 second.


3 Answers

You could opt for using web worker threads instead:

https://developer.mozilla.org/en-US/docs/DOM/Using_web_workers http://www.html5rocks.com/en/tutorials/workers/basics/

like image 62
asgoth Avatar answered Sep 27 '22 17:09

asgoth


What I would do:

http://jsfiddle.net/gunderson/4XXQ4/1/

    var severQueue = [];
    var delay;

    $("#inputSquare").mousemove(onMouseMove);

    function onMouseMove(){
        if (delay){
           clearTimeout(delay);
        }
        serverQueue.push("doSomething")
        delay = setTimeout(sendToServer, 1000);
    }

    function sendToServer(){
        console.log(serverQueue.length);
        delay = null;
        $("#inputSquare").addClass("activated");
        // do some ajax using serverQueue
        // we'll just simulate it with another timeout
        for (var i in serverQueue){
            serverQueue.pop();
        }
        onComplete = setTimeout(onAjaxComplete, 1000);
    }

    function onAjaxComplete(){
        $("#inputSquare").removeClass("activated");
    }

​
like image 25
Patrick Gunderson Avatar answered Sep 27 '22 16:09

Patrick Gunderson


In theory, your solution looks like it will work. There are no scoping problems related to you passing a callback function to your scheduler function; the callback will close over whatever environment it was created in, just like any other function in JavaScript. That being said, scoping rules can be a bit tricky in JavaScript, so make sure that you read up on it.

In practice, there may be some browser-specific issues related to setTimeout that may make this solution unworkable. For example, the frequency at which certain browsers execute setTimeout callbacks may vary such that you'll be waiting longer than you expect for a callback to be executed. All setTimeout callbacks will be executed sequentially; they'll never be executed in parallel. However, you have guarantees as to what order they will be executed in.

All that being said, any major gotcha in your solution will likely have more to do with the callbacks that your registering rather than the way in which you're registering them.

like image 36
seliopou Avatar answered Sep 27 '22 15:09

seliopou