【问题标题】:Correct way to callback function after all data have been retrieved from mongoDB in Express?在 Express 中从 mongoDB 检索到所有数据后回调函数的正确方法?
【发布时间】:2016-01-04 06:31:54
【问题描述】:

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

我的应用中的对话定义为 2 个不同的用户之间。例如,如果 Adam 刚刚创建了个人资料并向 Jane 发送了 1 条消息,向 Jack 发送了 3 条消息。他会有 2 次对话,但总共有 4 条消息。

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

public/javascripts/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);
    });
....
})

routes/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);
  // }
});

} });

【问题讨论】:

    标签: javascript angularjs node.js mongodb


    【解决方案1】:

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

    在此示例中,在$http(...) 之后返回了一个承诺。我建议使用 .then,而不是使用 .success。了解两者之间的区别很重要,因此我将尝试简要解释一下。这是 Angular 源代码中的 .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 更易于维护。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-28
      • 1970-01-01
      • 1970-01-01
      • 2021-07-23
      相关资源
      最近更新 更多