angular-node-socketio icon indicating copy to clipboard operation
angular-node-socketio copied to clipboard

Doesn't look like it handles arrays

Open nickretallack opened this issue 14 years ago • 1 comments

I haven't tested this code, but I can tell from the part where it's appending dots that it doesn't handle array indexes. It actually might be pretty easy to fix this: instead of appending things with dots, put them in brackets! That should work for both methods of indexing.

nickretallack avatar Aug 23 '11 14:08 nickretallack

I wrote this. I'm new to angular so it may not be perfect but it is working. I'm also new to GitHub. What is the best way to share my array handling code? I'll paste it here for now. I must saw that angular-node-socketio make angular freaking awesome. Forget meteor and Derby. Angular is a real time platform too, but much more mature. I'd like to update this to use socket.io rooms and channels. Also it would be better if I could share a scope object at any level instead of having one big global sharedModel. Then it would be perfect. This is a good start though and my array solution just makes it better.

At first I just passed the entire array. Doing a chat demo quickly showed me that this solution wouldn't be performant. I ended up doing an index by index comparison with the old array and only emitting those index that are new or different. inserting an item to the front of an array will trigger the worst case scenario where every index doesn't match and the whole array must be sync'd. It's better than doing that every time though I suppose.

Here is the code:

services.coffee:


angular.module('app.services', []) .factory( "sharedModel", ($rootScope) -> model = {} lastModel = angular.copy(model)

syncObject = (parent, src, dst) -> for name of src path = ((if parent then parent + "." else "")) + name # do nothing we are in sync if src[name] is dst[name]

  else if typeof src[name] is "object" and not Array.isArray(src[name])
    # we are an object, so we need to recurse
    syncObject path, src[name], dst[name] or {}

  else if Array.isArray(src[name]) and Array.isArray(dst[name])
    for arrayItem, i in src[name] when dst[name][i] isnt arrayItem
      path = path + "[" + i + "]"
      socket.emit "channel",
        path: path
        value: src[name][i]

      dst[name] = angular.copy(src[name])

  else
    socket.emit "channel",
      path: path
      value: src[name]

    dst[name] = angular.copy(src[name])

set = (obj, path, value) -> return angular.copy(value, obj) unless path lastObj = obj property = undefined angular.forEach path.split("."), (name) -> if name if name.indexOf("]") + 1 == name.length tmpName = name.substr(0, name.indexOf("[")) if Array.isArray(obj[tmpName]) index = name.substr( name.indexOf("[") + 1, name.indexOf("]") - name.indexOf("[") - 1) name = name.substr(0, name.indexOf("[")) lastObj = obj return lastObj[name][index] = value else lastObj = obj obj = obj[property = name] lastObj[property] = obj = {} unless obj

if  property != undefined
  lastObj[property] = angular.copy(value)

TODO: use scoket.io factory

http://www.html5rocks.com/en/tutorials/frameworks/angular-websockets/

socket = io.connect("http://localhost:8889/") socket.on "channel", (message) -> set model, message.path, message.value set lastModel, message.path, message.value $rootScope.sharedModel = model $rootScope.$apply()

$rootScope.$watch "sharedModel", (-> syncObject "", model, lastModel lastModel = angular.copy(model) ), true return model )

server.coffee:


express = require("express") fs = require("fs") io = require("socket.io").listen(8889)

for npm, otherwise use require('./path/to/socket.io')

Reducing socket.io log (debug) statements

io.set "log level", 2

app = express() app.get "/", (req, res) -> res.redirect "index.html"

app.configure -> app.use express.methodOverride() app.use express.bodyParser() app.use express.static(__dirname + "/../_public") app.use express.errorHandler( dumpExceptions: true showStack: true ) app.use app.router

app.listen 3333

set = (obj, path, value) -> lastObj = obj property = undefined path.split(".").forEach (name) -> if name if name.indexOf("]") + 1 == name.length tmpName = name.substr(0, name.indexOf("[")) if Array.isArray(obj[tmpName]) index = name.substr( name.indexOf("[") + 1, name.indexOf("]") - name.indexOf("[") - 1) name = name.substr(0, name.indexOf("[")) lastObj = obj return lastObj[name][index] = value else lastObj = obj obj = obj[property = name] lastObj[property] = obj = {} unless obj

if property != undefined lastObj[property] = value

model = {} clients = []

socket.io

io.sockets.on "connection", (socket) -> clients.push socket

new client is here!

socket.on "channel", (msg) -> console.log "message:" console.log msg set model, msg.path, msg.value clients.forEach (otherClient) -> if socket isnt otherClient console.log "emitting.." otherClient.emit "channel", msg

console.log msg

socket.emit "channel", path: "" value: model

gofreddo avatar Oct 11 '12 04:10 gofreddo