- From: Aaron Boodman <aa@google.com>
- Date: Mon, 3 Nov 2008 23:08:58 -0800
Hello all, A few months ago, I suggested that we combine the DedicatedWorker and SharedWorker interfaces (http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2008-September/016228.html), but we never reached consensus. Since Mozilla and Apple are both working on implementing this now, I'd like to revisit the issue before we end up with something non-ideal baked into implementations. My biggest issue with the proposal as currently drafted is that there are so many different ways to send and receive messages. I think this overcomplicates the proposal for both developers and implementors. For dedicated workers, you can either send single messages using the Worker object directly, like in Gears: var worker = new Worker("foo.js"); worker.postMessage("ping"); Or, you can use the more powerful startConversation() API to easily group related messages together: var port = worker.startConversation(); port.postMessage("ping"); Note that the worker has to know ahead of time which API the callers will use since the way that it replies is different depending on that. If the caller used Worker.sendMessage(), the worker should reply like this: onmessage = function() { postMessage("pong"); } ... but if the caller used Worker.startConversation().sendMessage(), then the worker should reply like this: onmessage = function(e) { e.port.postMesage("pong"); } SharedWorkers require a third, completely different API to send messages: var w = new SharedWorker("foo.js", "foo"); w.port.postMessage("ping"); w.port.onmessage = function(e) {}; The interface to receive messages in a SharedWorker is also special: onconnect = function(e) { e.port.onmessage = function(e) { e.port.postMessage("pong"); } } This lack of generality bothers me on an aesthetic level, but I also think it has the following real problems: * Workers have to know what interface was used to send them messages. If the page using a worker decide to start using a more powerful send API, the worker must also be upgraded. You can already see examples of this problem in the samples at the beginning of the draft. They are marked with the comments "// support being used as a shared worker as well as a dedicated worker". * Having different interfaces for each use case means that each new feature has to be added to each interface separately. We can already see this problem in the fact that the SharedWorker interface lacks startConversation() for no apparent reason. * Having multiple interfaces probably increases the chance of developers misunderstanding and using the wrong tool for the job. I can easily see developers accidentally reimplementing startConversation() on top of Worker.sendMessage(). * More API for developers to learn and implementors to build. I think that these issues can all be addressed by simplifying and combining the various APIs. This will make the simplest examples of workers require slightly more code, but I think it is much simpler and more elegant. Here is how it would work: * Get rid of the DedicatedWorker interface. * Add startConversation() to SharedWorker, but rename it "connect()" and make the onconnect event fire inside the worker each time it is called. Here's an example in code: // dedicated workers (outside) var worker = new Worker("foo.js"); var port = worker.connect(); port.onmessage = function() { } port.postMessage("ping"); // dedicated workers (inside) onconnect = function(e) { e.port.onmessage = function(e) { e.port.postMessage("pong"); } } Shared workers are exactly the same except the constructor is SharedWorker("foo.js", "foo"); Note that I do not think it is necessary to implement this all at once. For one, the SharedWorker constructor could easily be punted for future releases. Thoughts? - a
Received on Monday, 3 November 2008 23:08:58 UTC