Comments (10)
Hah, this was the next thing on my list.
Ideally, it'd be nice for Angular to automatically pass socket
to the factory, so the entire setup/teardown is transparent. I don't think there's a nice way to do that right now, so passing $scope
as an arg might be totally reasonable.
I'm going to think on it a bit and possibly consult my colleagues.
from angular-socket-io.
Another thought I had was to use module.decorator
to augment $scope
with a socket
API that cleans itself up when the scope is destroyed. I don't particularly like this solution though because it makes it less clear where the $scope.socket
comes from.
from angular-socket-io.
I agree about module.decorator
; I think given the choice I'd rather explicitly tie the service to the scope.
Have you given any thought to/how do you feel about a change to $rootScope
that would either
- allow you to be notified when any child scope of a scope is destroyed (e.g.
Scope#$destroy
calls$rootScope.$emit
or its own$emit
with some new event), allowing you to watch for a$destroy
event on any of a given set of scopes - similarly, allow you to be notified when new scopes are created (e.g.
Scope#$new
calls$rootScope.$emit
with some new event), allowing you to keep track of any created scopes, thus allowing you to watch for their$destroy
events
The topic on the AngularJS mailing list that lead to a discussion of the new scope event system (Event Bus in AngularJS) brought up the same kind of issue; some of the talk there makes me wonder if making it too easy to leak memory is a worry with this kind of technique.
from angular-socket-io.
New idea: forward socket events to $rootScope.broadcast
, prefixing the event name with socket:
or similar. This approach should gracefully handle scope deletion.
from angular-socket-io.
btford: the forwarding approach is what I'm doing, and now I'm trying to figure out a way to simulate promises (or something like that)
Currently I have something like this (using the socket wrapper that you wrote in an HTML5 blog -- thanks!)
]).controller('DefinitionAddCtrl', ['$scope', 'socket', ($scope, socket) ->
definitionAddedHandler = (definitionAdded) ->
console.log 'A definition was added:'
console.log definitionAdded
socket.handle 'DefinitionAdded', definitionAddedHandler
$scope.definitionAdd = ->
cmd =
word: $scope.word
definition: $scope.definition
socket.send 'DefinitionAdd', cmd
$scope.$on '$destroy', ->
socket.removeHandler 'DefinitionAdded', definitionAddedHandler
console.log 'the definition add controller is being destroyed'
])
Partly, I believe that some of these things I'm doing do not / should not use socket.io -- they would be simpler as PUT / POST or GET -- but for now I'm just trying to work through ideas quickly, so I want a way to make it feel more abstract in the controller.
My adaption of your code currently looks like this:
app.service 'socket', ['$rootScope', '$location', ($rootScope, $location) ->
socket = io.connect("http://localhost:8000")
handlerDeregistrationCallbacks = []
socketWrapper =
on: (topic, callback) ->
socket.on topic, ->
args = arguments
$rootScope.$apply ->
callback.apply socket, args
emit: (topic, data, callback) ->
socket.emit topic, data, ->
args = arguments
$rootScope.$apply ->
callback.apply socket, args if callback
send: (topic, data) ->
console.log "send: " + topic + " -> " + data
@emit "message", [topic, data]
invoke: (messageClassName, message) ->
console.log "recv: " + messageClassName + " -> "
console.log message
$rootScope.$broadcast messageClassName, message
removeHandler: (topic, handler) ->
for deregistrationCallback in handlerDeregistrationCallbacks
if deregistrationCallback.topic is topic and deregistrationCallback.handler is handler
console.log 'deregistering callback for topic: ' + topic
deregistrationCallback.deregister()
handle: (topic, handler) ->
deregistrationCallback = $rootScope.$on topic, (event, message) ->
handler message, $location, $rootScope
handlerDeregistrationCallbacks.push
topic: topic
handler: handler
deregister: deregistrationCallback
I suppose I could have just returned the deregistrationCallback to the caller and had the $destroy handler call it directly instead of storing it and looking it up.
But, in any case, I want to make it feel like less work in the controller. I'm thinking of an API like this:
.controller('DefinitionAddCtrl', ['$scope', 'api', ($scope, api) ->
$scope.definitionAdd
cmd = _.pick $scope, 'word', 'definition'
api.send 'DefinitionAdd', cmd, (err, definitionAdded) ->
if err?
# handle error somehow
console.log 'A definition was added successfully:'
console.log definitionAdded
# Would be nice to not have to do this part:
$scope.$on '$destroy', ->
api.removeHandlerFor 'DefinitionAdd'
])
from angular-socket-io.
Here's an initial cut at what I was saying, based on ideas from both of you, sorry for the Coffee if you don't dig it :)
First, my modified socket service with some things specific to my needs like invoke and send, followed by an apiFactory
which takes the current $scope as a parameter so that it can subscribe to $destroy and clean up its mess:
app.service 'socket', ['$rootScope', '$location', ($rootScope, $location) ->
socket = io.connect("http://localhost:8000")
handlerDeregistrationCallbacks = []
socketWrapper =
on: (topic, callback) ->
socket.on topic, ->
args = arguments
$rootScope.$apply ->
callback.apply socket, args
emit: (topic, data, callback) ->
socket.emit topic, data, ->
args = arguments
$rootScope.$apply ->
callback.apply socket, args if callback
send: (topic, data) ->
console.log "send: " + topic + " -> " + data
@emit "message", [topic, data]
invoke: (messageClassName, message) ->
console.log "recv: " + messageClassName + " -> "
console.log message
$rootScope.$broadcast messageClassName, message
handle: (topic, handler) ->
deregistrationCallback = $rootScope.$on topic, (event, message) ->
handler message, $location, $rootScope
return deregistrationCallback
socketWrapper
]
app.factory 'apiFactory', ['$rootScope', 'socket', ($rootScope, socket) ->
return (scope) ->
handlerDeregistrationCallbacks = {}
scope.$on '$destroy', ->
for responseTopicName, deregistrationCallback of handlerDeregistrationCallbacks
deregistrationCallback()
obj = send: (topic, data, handler, responseTopicName='') ->
if responseTopicName is ''
responseTopicName = topic + 'Complete'
if not handlerDeregistrationCallbacks[responseTopicName]?
deregistrationCallback = socket.handle responseTopicName, handler
handlerDeregistrationCallbacks[responseTopicName] = deregistrationCallback
socket.send topic, data
return obj
]
And, in my controller:
]).controller('DefinitionAddCtrl', ['$scope', 'apiFactory', ($scope, apiFactory) ->
api = apiFactory $scope
$scope.definitionAdd = ->
cmd =
word: $scope.word
definition: $scope.definition
api.send 'DefinitionAdd', cmd, (definitionAdded) ->
console.log 'A definition was added successfully:'
console.log definitionAdded
])
This is vastly simpler than what I had before:
.controller('DefinitionAddCtrl', ['$scope', 'socket', ($scope, socket) ->
definitionAddedHandler = (definitionAdded) ->
console.log 'A definition was added:'
console.log definitionAdded
socket.handle 'DefinitionAdded', definitionAddedHandler
$scope.definitionAdd = ->
cmd =
word: $scope.word
definition: $scope.definition
socket.send 'DefinitionAdd', cmd
$scope.$on '$destroy', ->
socket.removeHandler 'DefinitionAdded', definitionAddedHandler
console.log 'the definition add controller is being destroyed'
])
Hope this helps!
from angular-socket-io.
Thanks for the input, all.
I decided that this is the best way to handle it.
This method uses AngularJS's own event system and typically results in less boilerplate.
Feedback welcome.
from angular-socket-io.
I think the soltuion used by ngSocketIO ( .bindTo($scope)
) is more handy.
from angular-socket-io.
@jitowix it's trivial to implement this .bindTo($scope)
feature as a decorator building upon this module.
from angular-socket-io.
So how do I actually use the removeListener? As of now I do like this:
$scope.$on('$destroy', function() {
mySocket.removeListener();
});
and initiating them like this:
mySocket.on('TEST', function(msg) {
console.log(msg)
});
from angular-socket-io.
Related Issues (20)
- Best way to provide a socket URL as a parameter to the socketFactory HOT 1
- socket.on('init', function (data)
- how can i confirm the angular app is successful connected ? HOT 1
- How can i change the url at runtime? HOT 1
- Disconnect on state change HOT 1
- parse url in connect()
- request isn't sent on iOS 10.0 HOT 2
- Forwarding doesn't work with namespaces HOT 1
- socket.removeListener not working HOT 4
- Adding step 4 as a dependency.
- doesn't remove or empty array on listener after change route HOT 4
- adding support for AMD/Webpack HOT 3
- ion-nav-view won't load if btford.socket-io is add to dependency
- How to detect socket disconnect and reconnect HOT 1
- angular 2 support HOT 1
- Broadcast to all except sender
- Module 'btford.socket-io' is not available! HOT 1
- Change io.connect('http://localhost:3000/myNameSpace') to angular socket io version HOT 1
- scope.$on is not a function
- Do you know any v3 or higher server?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from angular-socket-io.