Using backbone.js with socket.io

2019-07-30 01:19发布

问题:

I'm trying to get into the node.js world and would like to build a simple but complete testing app to hook up node.js with socket.io and backbone.js using redis as a store. I found a couple of tutorials and a few examples as well. Somehow I just get confused about the whole architecture I have to use. Usually you'd define all your routes within your server.js with express. So you get a full control of your routes on the server side. Now linking up backbone you have to define routes again? This seems to be a model aspect but for me it seems like double-work which I somehow dislike. So did I just got confused and things work completely differently? Maybe someone has a link to a good tutorial or example where it's made more clear.

回答1:

Now linking up backbone you have to define routes again?

depends on what you mean by route.

you need to tell backbone where to find the server resources so it make sense for a model to tell it where to get it ( url parameter in the model ).

The route Class in backbone has nothing to do with routes on the server. It is just a way to change the application state or the displayed views within the page.

for instance in a LOB app you have a list view and a detail view.

backbone allows you to switch between the views via the router without refreshing the page.

the url for the list could be http://app.com/#list , the url for the detail view could be http://app.com/#detail/:id where id would be the product id. you can switch between views without refreshing the page just by clicking on a link defined as

<a href="#detail/1">product 1</a> 

and back to the list view

<a href="#list">product list</a>

then you can have a view that display a product form

<a href="#newproduct">Create a new product</a>

and so on. so you dont have to set up event listeners in your views to switch between views that should not be aware of each others, and that without requesting anything to the server and without page refresh. It is a conveniant way to structure your application.



回答2:

I'm using something similar for front-end Backbone Model

class Model extends Backbone.Model

    idAttribute: '_id'

    _sync: (method, model, options) =>
        options.data ?= {}
        @socket.emit method, @name(), model.toJSON(), options.data, (err, data) => 
            if err then console.error "error in sync with #{method} #{@.name()} with server (#{err})" else options.success(data)

    sync: (method, model, options) => 
        if @socket.connected() is no 
            @socket.once 'connect', => @_sync method, model, options
        else 
            @_sync method, model, options

    name: => 
        if @collection and @collection.name then return @collection.name else throw new Error "Socket model has no name (#{@.collection})"

    initialize: ->
        @socket = require('socket')

module.exports = Model

And this is my basic Backbone Collection

class Collection extends Backbone.Collection

    model: require('class/socket/model')

    _sync: (method, collection, options) =>
        @socket.emit method, @.name, collection.toJSON(), options.data, (err, data) => 
            if err then console.error "error in sync with #{method} #{@.name} with server (#{err})" else options.success(data)

    sync: (method, collection, options) => 
        if @socket.connected() is no 
            @socket.once 'connect', => @_sync method, collection, options
        else 
            @_sync method, collection, options

    garbage: false

    register: =>
        @socket.emit 'register', @name

    deregister: =>
        @socket.emit 'deregister', @name
        @garbage = true

    initialize: (options) ->
        @name = options.name if options and options.name
        if !@name then throw new Error 'Socket collection has no name'
        @socket = require('socket')

        # Registrating socket for connection
        @socket.on 'connect', => @register() if @garbage is off
        if @socket.connected() is yes then @register()

        @fetch()        

        # Registration for socket events for this collection
        @socket.on @name, (method, model) =>

            if method is 'reset'
                @reset(model)

            if method is 'delete'
                m = @get model._id 
                m.trigger 'destroy', m, m.collection

            if method is 'update'
                m = @get model._id
                m.set(model)

            if method is 'create'
                @add(model)

            console.log "SOCKET: " + method + " triggered for collection " + @name

module.exports = Collection;

It's CoffeeScript if you don't mind.

All tutorials that I have seen use register / deregister for collections.

The important stuff is to find a way to introduce authentication to the backend with those collections and models. It's not that hard, but it's tricky.

Also be careful for managing two socket connections by the same user. It needs to send socket update to the same user but to the other connection.