Node.js + Angular.js承诺同步问题

时间:2016-12-31 15:03:40

标签: angularjs node.js mongodb angular-promise

我正在开发一个聊天应用程序,它是服务器端的Node.js + MongoDB(Mongoose库),以及客户端的Angular.js。

我有一个房间的数据库集合(MongoDB)(应用程序中的所有房间),如下所示:

// ------- creating active_rooms model -------
var active_rooms_schema = mongoose.Schema({
    room_name: String,
    users: [String]
});
var active_rooms = mongoose.model('active_rooms', active_rooms_schema);

此数据库包含一个包含所有用户的房间(即#34;我的酷房"用户:"迈克","乔"和"戴夫"。)

我想要做的是 - 每次用户想要进入Angular.js客户端的聊天室(有一些房间名称)时,我想:

  1. 如果房间不存在则创建房间
  2. 将该用户推送到会议室的用户阵列中。
  3. 我知道因为1,我总会有一个有一系列用户的房间。

    这是我的Angular相关代码:(我不能在这里给出整个应用程序,因为它太大而且不相关。)

    $scope.enterRoom = function(info) {
        $q.when(create_room_if_not_exists($scope.room)).then(add_user_to_room($scope.name, $scope.room));
        $location.path("chat");
    }
    
    
    var create_room_if_not_exists = function(room_name) {
        var deferred = $q.defer();
        is_room_already_exists({
            'name': room_name
        }).then(function(response) {
            if (!response.data.is_room_exists) {
                register_room({
                    'name': room_name
                });
                console.log("room: " + room_name + ", was created");
                deferred.resolve();
            }
        }, function(error) {
            deferred.reject(error.data);
        });
        return deferred.promise;
    }
    
    var add_user_to_room = function(user_name, room_name) {
        console.log(user_name)
        add_user_to_room_request({
            'user_name': user_name,
            'room_name': room_name
        });
    }
    
    var is_room_already_exists = function(info) {
        return $http({
            url: '/is_room_already_exists',
            method: 'POST',
            data: info
        });
    }
    
    var add_user_to_room_request = function(info) {
        $http({
            url: '/add_user_to_room',
            method: 'POST',
            data: info
        });
    }
    
    var register_room = function(info) {
        return $http({
            url: '/register_room',
            method: 'POST',
            data: info
        });
    }
    

    第二个动作发生在第一个动作之前。当我将日志打印到控制台时,我看到了,我不知道为什么。

    这两个操作都是通过HTTP请求到达服务器的 - 所以我不认为问题就在那里。

2 个答案:

答案 0 :(得分:1)

试试这个:

$scope.enterRoom = function (info) {
  return create_room_if_not_exists($scope.room)).then(function(){
    return add_user_to_room_request({ 'user_name': $scope.name, 'room_name': $scope.name });
  }).then(function(){
    $location.path('chat');
  });
}


var create_room_if_not_exists = function (room_name) {
    var deferred = $q.defer();
    return is_room_already_exists({ 'name': room_name }).then(function (response) {
        if (!response.data.is_room_exists) {
            console.log("room: " + room_name + ", is being created");
            return register_room({ 'name': room_name });
        }
        return response;
    })
}

   var is_room_already_exists = function (info) {
        return $http({
            url: '/is_room_already_exists',
            method: 'POST',
            data: info
        });
    }

 var add_user_to_room_request = function (info) {
            return $http({
                url: '/add_user_to_room',
                method: 'POST',
                data: info
            });
        }

   var register_room = function (info) {
            return $http({
                url: '/register_room',
                method: 'POST',
                data: info
            });
        }

答案 1 :(得分:1)

  

我说的是XHR没有链接

链接问题的一个常见原因是未能将承诺退回链中:

var add_user_to_room = function(user_name, room_name) {
    console.log(user_name)
    //add_user_to_room_request({
    return add_user_to_room_request({
  //^^^^^^ ----- be sure to return returned promise
        'user_name': user_name,
        'room_name': room_name
    });
}

如果链接正确完成,则无需$q.defer

var create_room_if_not_exists = function(room_name) {
    //var deferred = $q.defer();
    //is_room_already_exists({
    return is_room_already_exists({
  //^^^^^^ --- be sure to return derived promise
        'name': room_name
    }).then(function(response) {
        if (!response.data.is_room_exists) {
            console.log("room: " + room_name + ", to be created");
            //register_room({
            return register_room({
          //^^^^^^ ----- return promise to further chain
                'name': room_name
            });
            //deferred.resolve();
        } else {
            return room_name;
          //^^^^^^ ----- return to chain data
        };
    }, function(error) {
        //deferred.reject(error.data);
        throw error;
      //^^^^^ ------- throw to chain rejection
    });
    //return deferred.promise;
}

如果正确退回承诺,则无需$q.when

$scope.enterRoom = function(info) {
    //$q.when(create_room_if_not_exists($scope.room))
    //   .then(add_user_to_room($scope.name, $scope.room));
    return create_room_if_not_exists($scope.room)
        .then(function() {
            return add_user_to_room($scope.name, $scope.room));
        }).then(function()
            $location.path("chat")
        });
}

功能编程的经验法则是 - 总是返回

因为调用promise的.then方法会返回一个新的派生promise,所以很容易创建一个promise链。可以创建任意长度的链和,因为承诺可以通过另一个承诺来解决(这将进一步推迟其解析),可以在任何点暂停/推迟承诺的解决。连锁,链条。这使得实现强大的API成为可能。

- AngularJS $q Service API Reference - Chaining Promises