setInterval and setTimeout JavaScript Functions

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);
}

Comments:

Just wondering - why this

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

instead of this?

Platform.runLater(func)

Posted by guest on September 26, 2013 at 04:51 PM PDT #

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.

Posted by jlaskey on September 26, 2013 at 06:47 PM PDT #

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?

Posted by guest on October 09, 2013 at 02:00 PM PDT #

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.

Posted by jlaskey on October 10, 2013 at 12:11 AM PDT #

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

Posted by Andrea Giammarchi on March 19, 2014 at 10:39 AM PDT #

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.

Posted by jlaskey on March 19, 2014 at 12:47 PM PDT #

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.

Posted by guest on May 08, 2014 at 03:13 PM PDT #

What does CallBackClass look like?

Posted by jlaskey on May 09, 2014 at 04:53 AM PDT #

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);
}
}

Posted by guest on May 09, 2014 at 05:26 AM PDT #

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

Posted by guest on May 09, 2014 at 11:29 AM PDT #

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.

Posted by Matthias on July 07, 2014 at 02:40 AM PDT #

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

Posted by jlaskey on July 07, 2014 at 03:34 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Technical discussions and status of the Nashorn JavaScript Project.

Search

Categories
Archives
« July 2015
SunMonTueWedThuFriSat
   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
       
Today