Async input processing using Neils JS-Interpreter

129 views
Skip to first unread message

Till Harbaum

unread,
Aug 15, 2018, 2:44:12 PM8/15/18
to Blockly
I am writing another fischertechnik robotics integration based on blockly. This time i am connecting an Arduino-like controller via WebUSB to the Browser running Blockly (IMHO actually a very fancy combination allowing Blockly to access the physical world).

All the basic things just work out of the box using Neils JS-Interpreter. But now i am struggling with the asynchronous nature of WebUSB IO when reading from the device.

Consider Blockly has generated code like
   port_set(1, port_get(2));

This is mirroring the state of input port 2 to output port 1.

I have JS-Interpreter API callbacks for port_set and port_get. In the JS interpreter this is handled as one statement and processed within one step. Unfortunately the port_get is massive async as it sends a USB request to the device and some time later receives a reply.

I have no nice idea how to deal with that. I would need to interrupt JS-Interpreter inside the API callback and resume processing once i receive the reply. But how?

Some brute force solutions would be to always save the JS-Interpreter state before each step and detect IO processing within the step. If there has been the need for IO then i could do that IO afterwards and reset the JS-Interpreter to the state before the statement requiring IO and then re-do the same statement a second time. This time i'd know the required values beforehand. I'd expect this to be very slow as i'd need to save the Interpreter state before each and every step.

A second solution would be to always read all inputs before doing one step and thus having all data already buffered should i need it within the step. This is also ugly as this would result in plenty of unneeded USB IO which would also slow things down significantly.

So both solutions are somewhat ugly ...  Any better idea?

Till Harbaum

unread,
Aug 15, 2018, 2:53:03 PM8/15/18
to blo...@googlegroups.com
Argh ... literally seconds after asking i found that the API has explicit
support for async IO as documented in https://neil.fraser.name/software/JS-Interpreter/docs.html ...

Sorry for the noise ...

Till
--
Dr. Till Harbaum <ti...@harbaum.org>

Till Harbaum

unread,
Aug 15, 2018, 4:17:13 PM8/15/18
to blo...@googlegroups.com
I am struggling to get this to work. Once i add an async API callback the
browser locks up to a point where i need to kill it.

I have reduced my setup to the minimal example below. The "run" button is
supposed to run the code "test();" in the JS Interpreter. This should then
wait for the event. And the "event" button is supposed to send that event. The
handler should then call callback with the value 42 from the event and the
Interpreter is supposed to finish processing. At least that's what i was hoping
for.

But once the API callback is invoked the browser becomes unresponsible. I
cannot even reload the page nor can i click the "event" button.

Regards,
Till

<!DOCTYPE html>
<html>
<head>
<script src="./acorn_interpreter.js"></script>
</head>
<body>
<button onclick="run()">JavaScript</button>
<button onclick="window.dispatchEvent(new CustomEvent('my_event', { detail:
42 }));">Event</button>
<script>
var initInterpreter = function(interpreter, scope) {
var wrapper = function(callback) {
console.log("test api called");
window.addEventListener('my_event', function (e) {
console.log("EVENT!!!"); callback(e.detail); }, false);
};
interpreter.setProperty(scope, 'test',
interpreter.createAsyncFunction(wrapper));
}

function run() {
var interpreter = new Interpreter('test();', initInterpreter);
do { go = interpreter.step(); } while(go);
console.log("DONE");
}
</script>
</body>
</html>

Andrew n marshall

unread,
Aug 15, 2018, 6:11:38 PM8/15/18
to blo...@googlegroups.com
Have you looked at the asynchronous execution demo (src)?
--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Till Harbaum

unread,
Aug 16, 2018, 1:58:35 AM8/16/18
to blo...@googlegroups.com
Thank you Andrew. I didn't see that one. At a first glance this looks interesting as it does not use the interpreters aforementioned async API feature.

Regards,
  Till

To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.

Andrew n marshall

unread,
Aug 16, 2018, 3:29:10 AM8/16/18
to blo...@googlegroups.com
Here is the line that registers the async function.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+unsubscribe@googlegroups.com.

Till Harbaum

unread,
Aug 16, 2018, 3:43:24 PM8/16/18
to blo...@googlegroups.com, Andrew n marshall
Hi Andrew,

that really helped me a lot. The thing is that when doing async APIs you must
not just run the interpreter constantly like i did:
do { go = interpreter.step(); } while(go);
instead you must take care for the async interruptions like e.g. so:
runner = function() {
if (interpreter.run()) {
setTimeout(runner, 10);
}
}
runner();

Thanks again,
Till

On Donnerstag, 16. August 2018 09:28:47 CEST Andrew n marshall wrote:
> Here
> <https://github.com/google/blockly/blob/master/demos/interpreter/wait_block.
> js#L61> is the line that registers the async function.
>
> --
> Andrew <http://anm.me/>
>
> On Wed, Aug 15, 2018 at 10:58 PM, 'Till Harbaum' via Blockly <
>
> blo...@googlegroups.com> wrote:
> > Thank you Andrew. I didn't see that one. At a first glance this looks
> > interesting as it does not use the interpreters aforementioned async API
> > feature.
> >
> > Regards,
> >
> > Till
> >
> > Andrew n marshall <a...@anm.me> schrieb am Do., 16. Aug. 2018, 00:11:
> >> Have you looked at the asynchronous execution demo
> >> <https://blockly-demo.appspot.com/static/demos/interpreter/async-executio
> >> n.html> (src
> >> <https://github.com/google/blockly/blob/master/demos/interpreter/async-ex
> >> ecution.html> )?
> >>
> >> --
> >> Andrew <http://anm.me/>
> >>> an email to blockly+u...@googlegroups.com.
> >>> For more options, visit https://groups.google.com/d/optout.
> >>
> >> --
> >> You received this message because you are subscribed to the Google Groups
> >> "Blockly" group.
> >> To unsubscribe from this group and stop receiving emails from it, send an
> >> email to blockly+u...@googlegroups.com.
> >> For more options, visit https://groups.google.com/d/optout.
> >
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Blockly" group.
> > To unsubscribe from this group and stop receiving emails from it, send an
> > email to blockly+u...@googlegroups.com.
> > For more options, visit https://groups.google.com/d/optout.


--
Dr. Till Harbaum <ti...@harbaum.org>
Reply all
Reply to author
Forward
0 new messages