X

setInterval and setTimeout JavaScript Functions

Jim Laskey
Senior Development Manager

With people porting HTML to Nashorn + JavaFX more frequently, I often get asked the question "how do you port functions like setInterval and setTimeout" (setInterval is used to have a function repeated at regular intervals, where setTimeout is used to have a function delayed.) The following code duplicates the functionality of the each of the setInterval family of functions, when used in a JavaFX application.

var Platform = Java.type("javafx.application.Platform");
var Timer = Java.type("java.util.Timer");
function setInterval(func, milliseconds) {

// New timer, run as daemon so the application can quit

var timer = new Timer("setInterval", true);

timer.schedule(function() Platform.runLater(func), milliseconds, milliseconds);


return timer;
}
function clearInterval(timer) {

timer.cancel();
}
function setTimeout(func, milliseconds) {

// New timer, run as daemon so the application can quit

var timer = new Timer("setTimeout", true);

timer.schedule(function() Platform.runLater(func), milliseconds);


return timer;
}
function clearTimeout(timer) {

timer.cancel();
}

<Update March 21, 2014>

I was requested by a reader to implement setInterval, setTimeout and setImmediate with the same arguments as defined in DOM.

var Platform = Java.type("javafx.application.Platform");
var Timer    = Java.type("java.util.Timer");
function setTimerRequest(handler, delay, interval, args) {
    handler = handler || function() {};
    delay = delay || 0;
    interval = interval || 0;
    var applyHandler = function() handler.apply(this, args);
    var runLater = function() Platform.runLater(applyHandler);
var timer = new Timer("setTimerRequest", true);
    if (interval > 0) {
        timer.schedule(runLater, delay, interval);
    } else {
        timer.schedule(runLater, delay);
    }
    return timer;
}
function clearTimerRequest(timer) {
timer.cancel();
}
function setInterval() {
    var args = Array.prototype.slice.call(arguments);
    var handler = args.shift();
    var ms = args.shift();
return setTimerRequest(handler, ms, ms, args);
}
function clearInterval(timer) {
clearTimerRequest(timer);
}
function setTimeout() {
    var args = Array.prototype.slice.call(arguments);
    var handler = args.shift();
    var ms = args.shift();

return setTimerRequest(handler, ms, 0, args);
}
function clearTimeout(timer) {
clearTimerRequest(timer);
}
function setImmediate() {
    var args = Array.prototype.slice.call(arguments);
    var handler = args.shift();

return setTimerRequest(handler, 0, 0, args);
}
function clearImmediate(timer) {
clearTimerRequest(timer);
}

Join the discussion

Comments ( 12 )
  • guest Thursday, September 26, 2013

    Just wondering - why this

    Platform.runLater(function() { func(); })

    instead of this?

    Platform.runLater(func)


  • jlaskey Friday, September 27, 2013

    My mistake. The original code was trying to create a closure to hold func.

    Wrapping the code in the setInterval function is sufficient. Updated the code

    above.


  • guest Wednesday, October 9, 2013

    This is a nice DOM event simulator. For those of us who are very interested in using Nashorn but also need a browser environment -- do you have any suggestions?


  • jlaskey Thursday, October 10, 2013

    Nothing specific to offer. There is a copy of env.js in the repo that works in Nashorn. Depending on your application, DOM to FX translates (manually) quite well. Having a complete DOM solution for Nashorn would take some time, but it is on the table.


  • Andrea Giammarchi Wednesday, March 19, 2014

    FYI above snippet is not ECMAScript standard. The setInterval should starts after `milliseconds` plus both setTimeout and setInterval, as well as setImmediate, accept 0, 1 or N arguments after the optional delay.

    Last, but not least, the moment you introduce `javafx.application.Platform` in the game `jjs` won't be a ble to run it anymore with or without `-fx` flag


  • jlaskey Wednesday, March 19, 2014

    Clearly, setInterval is wrong (corrected), but was merely to demonstrate how you would duplicate the functionality of DOM setInterval. Without an event loop, either supported by DOM or FX, setInterval, setTimer, setImmediate would have little meaning.


  • guest Thursday, May 8, 2014

    Hi, any idea how I can pass a method reference from Java to Nashorn via invokeFunction? For example:

    //JS:

    function foo(callback) {

    callback('bar');

    }

    //Java

    ...

    invocable.invokeFunction('foo', new CallBackClass()??)

    ...

    With everything I've tried, I get an error about method signature not matching, but I can't figure out what signature it's trying to use.


  • jlaskey Friday, May 9, 2014

    What does CallBackClass look like?


  • guest Friday, May 9, 2014

    The following example passes a method handle to invokeFunction - note that the cast is needed because invokeFunction accepts "Object"-s for arguments. javac can't figure out you're passing an @FunctionalInterface object without that cast to Consumer.

    import javax.script.*;

    import java.util.function.Consumer;

    public class Main {

    public static void main(String[] ar) throws Exception {

    ScriptEngineManager m = new ScriptEngineManager();

    ScriptEngine e = m.getEngineByName("nashorn");

    e.eval("function foo(callback) { callback('bar') }");

    ((Invocable)e).invokeFunction("foo",

    (Consumer<String>)System.out::println);

    }

    }


  • guest Friday, May 9, 2014

    Thank you! CallbackClass implemented Callable. This is much nicer.


  • Matthias Monday, July 7, 2014

    The first one is quite different in semantics to the JS functions, because the timer callbacks get invoked on a Timer thread instead of the JS event loop. This will get you some ugly multithreading problems.


  • jlaskey Monday, July 7, 2014

    Not sure which comment you are responding to, but Platform.runLater causes the task to run on the main thread.


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha
Oracle

Integrated Cloud Applications & Platform Services