-
Notifications
You must be signed in to change notification settings - Fork 3
CallbackJS
When extending the Javascript APIs (see ExtendJS for more info), the Javascript APIs must use background threads to handle long and expensive calls.
This is to prevent locking the main thread which is responsible of reacting to user events, executing Javascript code, propagating VRML events and doing all the graphic rendering.
To be able to notify some Javascript code that a background thread as terminated its work, one must use Javascript callbacks.
Look at the following Javascript example of the Browser.setTimeout()
method that calls a methods after a given amount of time:
function initialize () {
// call the myCallback in 2 seconds with two parameters
Browser.setTimeout (myCallback, 2000, 'hello', 'world');
}
function myCallback (firstArg, secondArg, now) {
Browser.print ('callback called with arg1:'+firstArg+' arg2:'+arg2+' at time '+now);
}
The initialize()
method returns immediately after the call to Browser.setTimeout()
.
The player will then automaticaly call the myCallback()
method after the given amount of time has elapsed.
To call a javascript callback, the calling code must retain a reference to the Script node that called the function and the ID
of the function that must be called in the Script.
It must then register the call to the callback by calling the addCallback
of the Script with the ID
and the arguments for the callback.
Then a call to the MiniPlayer.wakeUpCanvas()
static method must be done to force the main thread to wake up (in case it was sleeping, which is normaly always the case when no animation or event propagation occurs).
To illustrate this, we will build a naive implementation of the Browser.setTimeout()
method that will just spawn a thread that will sleep the given amount of time and then call Javascript callback.
case 0: // delayCall (int cb, int delay, [args])
final Script script = c.script; // keep a ref to the current Script
final int cb = registers[r].getInt (); // keep the ID of the JS callback
final int delay = registers[r+1].getInt (); // keep the delay
// Keep all the optional parameters
final Register[] params = new Register[nbParams-2];
for (int i = 0; i<nbParams-2; i++) {
params[i] = new Register ();
params[i].set (registers[r+2+i]);
}
new Thread () {
public void run () {
// sleep the given delay
Thread.sleep (delay);
// ask the Script to call the callback with given parameters
script.addCallback (cb, params);
// wakeup the main thread
MiniPlayer.wakeUpCanvas ();
}
}.start();
break;