从Express中的mongoDB中检索到所有数据后,是否正确回调函数?

时间:2016-01-03 21:26:11

标签: javascript angularjs node.js mongodb

我正在编写带有消息功能的Web应用程序。

我的应用中的对话定义为2个不同的用户。例如,如果Adam刚刚创建了一个配置文件并向Jane发送了1条消息,并向Jack发送了3条消息。他将有2次对话,但总共有4封信息。

在Express方面的以下代码中,我尝试检索数据库中给定用户的所有对话。 完成后,将此数据发送到Angular控制器端。 考虑到JS是异步的,在下面的api.js中执行此操作的正确方法是什么?

公开/ Javascript角/ main_controller.js

var mainApp = angular.module('myApp', ['ngRoute', 'btford.socket-io', 'xeditable']);
...
mainApp.controller('MessagesController', function($scope, $http, userSessionService, socket, focus){
  console.log("MessagesController running");
  $scope.messageDisplay = '';
  $scope.username = userSessionService.getUserSession().username;

  $http({
      url: '/loadConversations', 
      // url: '/about', 
      method: "GET"
    })
    .success(function(response) {
      console.log("success with loadConversations: ", response);
      console.log(response[0].data);
    });
....
})

路由/ api.js:

...

router.route('/loadConversations')
.get(isAuthenticated, function(req, res) {
var result = [];
  //Find Conversation with each and all distinct users
  for(var i = 0; i < req.user.conversations.length; i++){
Conversation.findOne({'_id': req.user.conversations[i]}, function(err, conversation){
  if(err){
    console.log(err);
  }
  if(conversation){
    var contactUsername = (conversation.initiatorUsername == req.user.username) ? conversation.responderUsername : conversation.initiatorUsername;
    var lastMessage = conversation.messages[conversation.messages.length-1].content;
    var dateOfMessage = conversation.messages[conversation.messages.length-1].date;
    var resultJSON = {contactUsername: contactUsername,
                            lastMessage: lastMessage,
                            dateOfMessage: dateOfMessage};
    result.push(resultJSON);

  } else {
    console.log("conversation not found!");
  }
  //Below is not working, where should I put res.json(result)?
  // if(result.length == req.user.conversations.length){
  //   res.json(result);
  // }
});

} });

1 个答案:

答案 0 :(得分:0)

我不确定你是否要求这样做,但我认为你应该稍微改写你的控制器代码。

在此示例中,在$http(...)之后返回承诺。而不是使用.success我会建议使用.then。了解两者之间的区别非常重要,因此我将尝试简要解释一下。这是角度源代码中的.success()方法:

promise.success = function(fn) {
// ...
promise.then(function(response) {
    fn(response.data, response.status, response.headers, config);
});
    return promise;
};

这是他们的official documentation

.success.then相同,但success除了成功调用结果的第一个参数,因此您不必写出response.data 。它有点方便,但是如果你曾经使用过缓存或想要将其他承诺链接起来,那就会成为一种痛苦。这是我的另类选择。

$http({
  url: '/loadConversations', 
  // url: '/about', 
  method: "GET"
})
.then(function(response) {
  // this is your success callback
  console.log("success with loadConversations: ", response);
  console.log(response[0].data);
}, function(error) {
  // if the service call doesnt return 200, we fire this
  console.log(error); 
});

此控制台日志将在此实现中异步执行,并且比使用.success更容易维护。

编辑:对于routes / api.js,我认为你只需要返回results数组

if(result.length == req.user.conversations.length){
  return result;
}