10

If I call connect from doStuff, I get the message that "the socket is connected", but the callback is not called. What am I missing here?

 $scope.connect = function() {
    var defer = $q.defer();
    ws = new WebSocket("ws://server.com:port");
    ws.onopen = function(){  
        console.log("Socket connected");
        defer.resolve("socket connected");
    };
    return defer.promise;
}

$scope.doStuff = function() {
    $scope.connect().then(function(data) {
        console.log("And we're off!", data);
    });
}
StepUp
  • 36,391
  • 15
  • 88
  • 148
dndr
  • 2,319
  • 5
  • 18
  • 28

2 Answers2

25

In AngularJS promise results are propagated asynchronously, inside a $digest cycle. So, your callback function registered with then() will only be called upon entering a $digest cycle.

So, when your socket connects, we are in a digest cycle. then() creates a new promise, but the results of that then() will not be propagated until the next digest cycle, which never comes (because there is no $timeout, or $http, or DOM event to trigger one). As @Ajay just posted, if you add $scope.$apply(), it will cause a digest cycle and you'll see the results.

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
8

You should be using $scope.$apply() please find the below working code

function formctrl($scope,$q,$timeout) {
            $scope.connect = function () {
                var defer = $q.defer();
                var ws = new WebSocket("ws://echo.websocket.org");
                ws.onopen = function (evt) {
                    defer.resolve("socket connected");
                    $scope.$apply();
                }
                return defer.promise;
            }

            $scope.raise = function () {
                $scope.connect().then(function (data) {
                    alert(data);

                });
            }


        }
Ajay Beniwal
  • 18,857
  • 9
  • 81
  • 99