Re: Synchronous postMessage for Workers?

On Thu, Nov 17, 2011 at 1:37 PM, Joshua Bell <jsbell@chromium.org> wrote:

> Jonas and I were having an offline discussing regarding the synchronous
> Indexed Database API and noting how clean and straightforward it will allow
> Worker scripts to be. One general Worker issue we noted - independent of
> IDB - was that there are cases where Worker scripts may need to fetch data
> from the Window. This can be done today using bidirectional postMessage,
> but of course this requires the Worker to then be coded in now common
> asynchronous JavaScript fashion, with either a tangled mess of callbacks or
> some sort of Promises/Futures library, which removes some of the benefits
> of introducing sync APIs to Workers in the first place.
>
> Wouldn't it be lovely if the Worker script could simply make a synchronous
> call to fetch data from the Window?
>
> GTNW.prototype.end = function () {
>     var result = self.sendMessage({action: "prompt_user", prompt: "How
> about a nice game of chess?"});
>     if (result) { chess_game.begin(); }
> }
>

We discussed a very similar thing about a year ago; I've been meaning to
bring that up again, so this is probably as good a time as any.
http://lists.w3.org/Archives/Public/public-webapps/2010OctDec/1075.html

The proposal is to allow polling a MessagePort, causing the first queued
message, if any, to be dispatched (or alternatively, to be returned).  This
could be easily extended to handle the above, by adding a "blocking
duration" parameter.

For example, working from Jonas's getMessageIfExists proposal:

  self.sendMessage({action: "prompt_user", prompt: "How about a nice game
of chess?"});
  var msg = messagePort.getMessageIfExists(5.0);
  if(msg && msg.data) { chess_game.begin(); }

Here, 5.0 means to block for five seconds (with a sentinel like -1 would
mean "block forever"), and the return value is the MessageEvent, returning
null if no message is received.

I preferred the "dispatch the first message" approach before, but your
blocking use case may make the "return the first message" approach better.

I think this is a fundamental missing piece to worker communication.  A
basic reason for having Workers in the first place is so you can write
linear code, instead of having to structure code to be able to return
regularly (often awkward and inconvenient), but currently in order to
receive messages in workers you still have to do that.

The use case that lead me to this initially was wanting to cancel
operations cleanly, without having to terminate and reinitialize the worker
entirely, eg. for input completion where processing restarts on each
keypress.  (That was an issue because the completion was initialized from
localStorage, making startup expensive; IndexedDB will help that particular
example, but this applies to any worker with nontrivial startup times.)

-- 
Glenn Maynard

Received on Thursday, 17 November 2011 19:28:38 UTC