Skip to content

Instantly share code, notes, and snippets.

@blakef
Last active August 29, 2015 14:28
Show Gist options
  • Save blakef/5864d9a8bfbb1e89eb9a to your computer and use it in GitHub Desktop.
Save blakef/5864d9a8bfbb1e89eb9a to your computer and use it in GitHub Desktop.
zGVmyY
div(ng-app="app", ng-controller="ctrl")
p {{ a }}
p(ng-controller="nested") {{ b }}
/**
* Pub/sub example using private $scope and callbacks.
*/
angular
.module('app', [])
// I don't like that we signal a change in our Factories by flipping a boolean value:
//
// $scope.update = !$scope.updated
// $rootScope.$apply();
//
// Then in all of our listeners we see this pattern:
//
// $scope.$watch(function() {
// return Factory.update;
// });
//
// This code intends to trigger a function call to update values on a local $scope in a directive
// or controller.
//
// Problems:
// - Lot of code which doesn't actually relate to the task
// - triggers a $digest cycle to notify us of an event outside of the angular $scopes? I don't see
// a way around this.
// - $watch polls the values a couple of times. Not the end of the world, and Object.observe goes a
// long way to eliminate the performance impact (although not widely available, see watchtower.js)
//
// Alternative:
.controller('ctrl', (Test, $scope) => {
$scope.a = "foo";
Test.update(msg => $scope.a = msg);
Test.message('This is a test?');
})
.controller('nested', (Test, $scope, $timeout) => {
$scope.b = "bar";
Test.update(msg => $scope.b = `Message B: ${msg}`);
$timeout( () => Test.message('A second message'), 2000);
})
.factory('Test', ($rootScope) => {
let event = {};
['Message', 'Opened', 'Closed', 'Error'].map(x => event[x] = x)
var socket = new WebSocket("ws://echo.websocket.org");
var events = $rootScope.$new(true);
let promise = new Promise( (resolve, reject) => {
socket.onmessage = (e) => {
events.$emit(event.Message, e.data);
// Having to run a $digest cycle isn't performant, but we have to
// do this to update $scope as this factory would be used widely
// in the application.
$rootScope.$apply();
}
socket.onopen = (e) => {
events.$emit(event.Opened, e);
resolve(e);
}
socket.onerror = (e) => {
events.$emit(event.Error, e);
reject(e);
}
socket.onclose = (e) => events.$emit(event.Closed, e);
});
events.$on('$destroy', socket.close);
return {
update: callback => events.$on(event.Message, (e, m) => callback(m)),
message: message => promise.then(() => {
socket.send(message);
})
};
})
;
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.min.js"></script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment