meta
meta copied to clipboard
Efficiently handling WebSockets
In Dojo 1.x, WebSockets are mostly an afterthought in how we approach APIs, with most examples using traditional XHR calls, and all provide store implementations using XHR.
For Dojo 2, I think it would nice if it was clear how WebSockets are used. The native APIs for WebSocket events are rather basic, which over the years led to dojox/socket and tube.
As such I think we should consider:
- Do we provide an API for WebSockets similar to our handling of dojo/request? The challenge in the past was that it doesn't follow a traditional request/response paradigm, and is more akin to our other event-driven paradigms. If so, do we bother with falling back to long-polling and introducing reconnection logic (needed for some networks and firewalls))
- Do we provide an out of the box module for stores to be backed by a WebSocket for data updates?
- Are there other considerations we need to make for real-time data updates (with Dojo 1.x, dgrid handles this pretty well out of the box, charting was always quite a bit of work). I imagine this fits nicely into our architecture and vdom approach and is easier to make work with Dojo 2.
While I don't have a strong opinion on several of these points, I do think that wrapping WebSockets in a dojo/request-like interface makes a lot of sense.
While WebSockets can improve the speed of a web application, I would argue that the primary feature that they provide is the ability to allow the server to initiate communication with a client. Given that, there are several other technologies that support that as well (e.g. HTTP/2 server push, Server-sent events, ...). While a developer would certainly have to provide some information about how to setup the connection to the server, I would imagine that the interaction with the connection after that could probably be hidden behind a fairly robust abstraction. Using a dojo/request-style interface would allow 80% of the use-cases to simply interact with the abstraction, thus removing the need to understand each technology. For more demanding scenarios the details could be exposes just like dojo/request/xhr exposes the details of the XMLHttpRequest.
Expanding on @vansimke's thoughts, in some ways the way a promise is to a stream or observable is like an XHR is to a WebSocket, in that promises/XHR resolve once and that's it, whereas streams/WebSockets may be resolved many times. So I'm wondering if the API around a WebSocket should be more of an Observable or a stream than something that returns a single promise?
Observables make sense from the perspective of the server sending data down to the client, but there would also have to be an aspect of the API to cover the ability to push a message back up. If we continue on the idea of some sort of interface that could be implemented by WebSockets and others, then those implementations that don't provide a native client-side push would have to have a fall back (e.g. an implementation that uses server-sent events might use regular XHRs to generate client-side messages).
I think that the beauty of this approach is that any kind of "real-time store", or similar consumer of real-time data could rely on the interface, and not be concerned about how that data is getting there. That would also help to future-proof those components in the event that another real-time strategy comes along.
What use cases are driving this need? At the moment I am not seeing a use case that would make this a priority.
The use case in my mind was connecting the dots on how to best use WebSockets with Dojo 2. With Dojo 1, it never felt like we really had thought through the usage, so it always felt like a bit of a hack.
I'm sure once dgrid 2 is ready, people will want to see the demo of a real-time stock quote chart (I'm sure Lightstreamer will want to create a demo early on for example).
So if we don't have some sort of WebSocket-wrapper, that's fine, but we should at a minimum document the right way to use WebSockets with Dojo 2.