AngularJS - 与notify()相关的承诺的奇怪行为

时间:2013-08-28 01:41:15

标签: promise

由于我想在AngularJS中实现聊天,我想使用promise / deferred原则。我的ChatService如下所示:

factory('ChatService', ['$q', '$resource', function($q, $resource) {

            var Service = {};
            var connected = false;
            var connection;

            var chatResource = $resource('/guitars/chat/:action', {action: '@action'}, {
                requestChatroomId: {
                    params: {
                        action: 'requestChatroomId'
                    },
                    method: 'GET'
                },
                sendMessage: {
                    params: {
                        action: 'sendMessage'
                    },
                    method: 'POST'
                }
            });

            Service.connect = function(cb) {

                var deferred = $q.defer();

                chatResource.requestChatroomId(function(data) {

                    connection = new WebSocket('ws://127.0.0.1:8888/realtime/' + data.chatroomId);

                    connection.onerror = function (error) {
                        deferred.reject('Error: ' + error);
                    };

                    connection.onmessage = function (e) {
                        cb.call(this, e.data);
                        deferred.notify(e.data);
                    };

                    connected = true;
                });

                return deferred.promise;
            };

            Service.sendMessage = function(msg) {
                if(!connected) {
                    return;
                }
                chatResource.sendMessage({message: msg});
            }

            return Service;
        }])

我使用ChatService的控制器是:

app.controller('ChatCtrl', ['$scope', 'ChatService', function($scope, ChatService) {
        $scope.chat = {};
        $scope.chat.conversation = [];

        var $messages = ChatService.connect(function(message) {
            $scope.$apply(function() {
                // #1 THIS FIRES EVERY TIME
                $scope.chat.conversation.push(message);
            });
        });

        $messages.then(function(message) {
            console.log('Finishes - should never occur!')
        }, function(error) {
            console.log('An error occurred!')
        }, function(message) {
            // #2 THIS FIRES ONLY IF THERE IS AN INTERACTION WITH THE ANGULAR MODEL
            console.log(message);
        });

        $scope.sendMessage = function(event) {
            ChatService.sendMessage($scope.chat.message);
            $scope.chat.message = '';
        };
    }]);

如果从服务器推送了某些内容,则会调用回调#1,但在与角度模型进行某些交互之前不会调用回调#2,即开始在输入框中写入内容。这种行为的原因是什么?

1 个答案:

答案 0 :(得分:0)

好的原因是,AngularJS并未发现变化。所以我将$ rootScope注入我的ChatService

factory('ChatService', ['$q', '$resource', '$rootScope', function($q, $resource, $rootScope) {

并且在connection.onmessage我在$ rootScope上调用$ apply():

connection.onmessage = function (e) {
  deferred.notify(e.data);
  $rootScope.$apply();
};