There are two things that I still do not have working in my Dart WebSocket implementation: sub-protocols and a scheme for different CRUD operations. The first is (hopefully) just an implementation detail of websockets. The latter is more a matter of me choosing something.
First up sub-protocols, which is an optional means to allow the server to specialize how to handle certain kinds of traffic. In the backend, I might specify the "comics-protocol" to handle changes to my comic book data store:
wsServer.on('request', function(request) { var connection = request.accept("comics-protocol", request.origin); console.log((new Date()) + ' Connection accepted.'); connection.on('message', function(message) { /* ... */ } }(this is still using WebSocket-Node in my node.js backend)
Back in Dart I try variations of:
WebSocket ws; main() { HipsterSync.sync = wsSync; ws = new WebSocket("ws://localhost:3000/", protocols: ["comics-protocol"]); // ... }But I only end up with variations of:
Internal error: 'http://localhost:3000/scripts/main.dart': Error: line 14 pos 21: invalid arguments passed to constructor 'WebSocket' for interface 'WebSocket' ws = new WebSocket("ws://localhost:3000/", protocols: ["comics-protocol"]);Digging through the source code a bit, it really seems that the Dart constructor only accepts a single argument. In other words, this seems like a TODO for Dart. No matter, I can live with that in my one-protocol app and can always make a notation that this is not baked when I discuss it in Dart for Hipsters.
After reverting, I change my attention to operations other than "read". In the client, I update my websocket-based Hipster MVC sync layer to send specialized messages depending on the CRUD method being used:
wsSync(method, model) { final completer = new Completer(); String message = "$method: ${model.url}"; if (method == 'delete') message = "$method: ${model.id}"; if (method == 'create') message = "$method: ${JSON.stringify(model.attributes)}"; print("sending: $message"); ws.send(message); // ... }On the back end, I then parse these messages with simple regular expressions:
connection.on('message', function(message) { if (message.type === 'utf8') { console.log('Received Message: ' + message.utf8Data); if (/^read/.test(message.utf8Data)) { connection.sendUTF(jsonComics()); } else if (/^create: (.+)/.test(message.utf8Data)) { var comic = createComic(JSON.parse(RegExp.$1)); connection.sendUTF(comic); } } });And amazingly, that just works. When I create a new comic book, the JSON representation of that new object comes back over the websocket, which is already sending the message to the collection via a Future:
wsSync(method, model) { final completer = new Completer(); String message = "$method: ${model.url}"; if (method == 'delete') message = "$method: ${model.id}"; if (method == 'create') message = "$method: ${JSON.stringify(model.attributes)}"; print("sending: $message"); ws.send(message); // Handle messages from the server, completing the completer ws. on. message. add((event) { print("The data in the event is: " + event.data); completer.complete(JSON.parse(event.data)); }); return completer.future; }Hitting one out of two goals ain't bad for tonight. I have never used websocket sub-protocols directly, so I have no real idea how important they are. They do seem like a nice-to-have. Regardless, it is good to see my Hipster MVC library holding up so far.
Day #326
No comments:
Post a Comment