数据库查询中的异步

时间:2013-07-16 13:28:17

标签: javascript node.js asynchronous

使用 node.js 时遇到问题。所有人都试图在对代码的评论中进行描述。

首先我需要构建一个对话框数组,其中包含有关对话者和最后一个meggase的信息。

IM = {
    iUserId: false,
    socket: false,
    checkDialog: function(socket) {
        this.socket = socket;
        // Returned [{owner: 123, viewer: 432}]
        var sql = 'SELECT DISTINCT(`owner_user_id`), `viewer_user_id` FROM `phpfox_mail` WHERE `owner_user_id` = ' + this.iUserId + ' GROUP BY 1,2 UNION SELECT DISTINCT (`viewer_user_id`), `owner_user_id` FROM `phpfox_mail` WHERE `viewer_user_id` = ' + this.iUserId + ' GROUP BY 1,2 ORDER BY 1 ';

        connection.query(sql, function(err, rows) {
          if (err) throw err;

          async.map(rows, function(item, nextParent) {
              var sql = 'SELECT `mail_id`, `subject`, `preview`, `owner_user_id`, `viewer_user_id`, `viewer_is_new`, `time_stamp` FROM `phpfox_mail` WHERE (`viewer_user_id` = ' + item.viewer_user_id + ' OR `owner_user_id` = ' + item.viewer_user_id + ') AND (`viewer_user_id` = ' + item.owner_user_id + ' OR `owner_user_id` = ' + item.owner_user_id + ') ORDER BY `mail_id` DESC LIMIT 1';
              var dialogs = [];
              connection.query(sql, function(err, rows) {
              // ???
              });

          }, function(err, item) {
              // Here I have to get the generated array with all the necessary dialogue.
              console.log(item);

              IM.socket.emit('logger', {text: 'dataIsABuilding', key: 'success'});
              IM.socket.emit('dialogsBuilding', item);
          });
        });
    }
};

目标:创建有关消息和对话者的信息数组。

方案:

  1. 与所有对话者联系。 [{owner_user_id:5757,viewer_user_id:5866},{etc ...}]
  2. 使用段落编号1的结果,从对话中获取有关最新报告的一系列信息。 [{mail_id:98,subject:test,owner:5757,viewer:5866,timestamp:123566544},{etc ...}]
  3. 获取有关指定标识符的用户的信息(owner_user_id / viewer_user_id)。
  4. 收集同一阵列中对话框的所有数据。
  5. 我在第三段停了下来。也就是说,我不知道如何一致地获取有关前两个阵列中用户的信息。

    请帮助我!

3 个答案:

答案 0 :(得分:1)

我不相信你正确使用async.map函数。不幸的是,你使用它是如此错误,我无法确定你实际上是在做什么。但是这里有一个关于你如何滥用的解释,以及正确使用async.map函数。

异步文档中的示例:

async.map(['file1','file2','file3'], fs.stat, function(err, results){
    // results is now an array of stats for each file
});

让我们稍微简化一下。

async.map(someArray, someFunction, someCallBack);

我相信你的问题在于someFunction参数。这是你的版本:

function(item, nextParent) {
    var sql = 'SELECT `mail_id`, `subject`, `preview`, `owner_user_id`, `viewer_user_id`, `viewer_is_new`, `time_stamp` FROM `phpfox_mail` WHERE (`viewer_user_id` = ' + item.viewer_user_id + ' OR `owner_user_id` = ' + item.viewer_user_id + ') AND (`viewer_user_id` = ' + item.owner_user_id + ' OR `owner_user_id` = ' + item.owner_user_id + ') ORDER BY `mail_id` DESC LIMIT 1';
    var dialogs = [];
    connection.query(sql, function(err, rows) {
        // ???
    });
}

如果我们参考fs.Stat示例,这个参数的函数应该有两个参数,第一个是我们发送到async.map的数组中的一个项。这一部分我相信你是对的。 HOwever,第二个参数是回调,有两个参数。错误和一组结果。这是我认为你搞砸的部分。你应该调用这个回调。内部async.map提供回调参数,此回调参数是async.map如何将结果收集到数组中。如果没有这个调用,async.map就无法收集结果。

我相信你想要的是:

function(item, someCallBackArgument) {
    var sql = 'SELECT `mail_id`, `subject`, `preview`, `owner_user_id`, `viewer_user_id`, `viewer_is_new`, `time_stamp` FROM `phpfox_mail` WHERE (`viewer_user_id` = ' + item.viewer_user_id + ' OR `owner_user_id` = ' + item.viewer_user_id + ') AND (`viewer_user_id` = ' + item.owner_user_id + ' OR `owner_user_id` = ' + item.owner_user_id + ') ORDER BY `mail_id` DESC LIMIT 1';
    var dialogs = [];
    connection.query(sql, function(err, rows) {
        someCallBackArgument(err, rows);
    });
}

答案 1 :(得分:1)

我假设这是一个关于如何使用async.map的问题: 我重写了你的代码,所以它正确地使用了回调: 您需要调整输出,但这应该返回一个包含您需要的所有数据的数组。

connection.query(sql, function(err, rows) {
      if (err) throw err;

      async.map(rows, function(item, callback) {
          var sql = 'SELECT `mail_id`, `subject`, `preview`, `owner_user_id`, `viewer_user_id`, `viewer_is_new`, `time_stamp` FROM `phpfox_mail` WHERE (`viewer_user_id` = ' + item.viewer_user_id + ' OR `owner_user_id` = ' + item.viewer_user_id + ') AND (`viewer_user_id` = ' + item.owner_user_id + ' OR `owner_user_id` = ' + item.owner_user_id + ') ORDER BY `mail_id` DESC LIMIT 1';
          var dialogs = [];
          connection.query(sql, function(err, rows) {
            if(err) return callback(err);
            callback(null, { item: item, rows: rows} );
          });

      }, function(err, item) {
          // Here I have to get the generated array with all the necessary dialogue.
          console.log(JSON.stringify(item));

          IM.socket.emit('logger', {text: 'dataIsABuilding', key: 'success'});
          IM.socket.emit('dialogsBuilding', item);
      });
    });

答案 2 :(得分:0)

是的! :)

IM = {
    iUserId: false,
    socket: false,
    checkDialog: function(socket) {
        this.socket = socket;
        var sql = 'SELECT DISTINCT(`owner_user_id`), `viewer_user_id` FROM `phpfox_mail` WHERE `owner_user_id` = ' + this.iUserId + ' GROUP BY 1,2 UNION SELECT DISTINCT (`viewer_user_id`), `owner_user_id` FROM `phpfox_mail` WHERE `viewer_user_id` = ' + this.iUserId + ' GROUP BY 1,2 ORDER BY 1 ';
        connection.query(sql, function(err, rows) {
          if (err) throw err;

          async.map(rows, function(item, nextParent) {
              var sql = 'SELECT `mail_id`, `subject`, `preview`, `owner_user_id`, `viewer_user_id`, `viewer_is_new`, `time_stamp` FROM `phpfox_mail` WHERE (`viewer_user_id` = ' + item.viewer_user_id + ' OR `owner_user_id` = ' + item.viewer_user_id + ') AND (`viewer_user_id` = ' + item.owner_user_id + ' OR `owner_user_id` = ' + item.owner_user_id + ') ORDER BY `mail_id` DESC LIMIT 1;';
              var dialogs = [];
            connection.query(sql, function(err, rows) {
              if(err) return nextParent(err);
              nextParent(null, rows[0]);
            });

          }, function(err, item) {             
             async.map(item, function(dialog, next) {
                 connection.query('SELECT `user_name`, `full_name`, `user_profile_image` FROM `phpfox_user` WHERE `user_id` = ' + dialog.owner_user_id, function(err, user) {
                     next(err, {owner: user[0], dialog: dialog});
                 });
             }, function(err, rows) {                 
                 async.map(rows, function(dialog, next) {
                     connection.query('SELECT `user_name`, `full_name`, `user_profile_image` FROM `phpfox_user` WHERE `user_id` = ' + dialog['dialog']['viewer_user_id'], function(err, user) {
                         next(err, {viewer: user[0], dialog: dialog['dialog'], owner: dialog['owner']});
                     });
                 }, function(err, dialogs) {
                     console.log(dialogs);
                     IM.socket.emit('logger', {text: 'dataIsABuilding', key: 'success'});
                     IM.socket.emit('dialogsBuilding', dialogs);
                 });                 
             });
          });
        });
    }

它有效!:)

Screen http://screencloud.net//img/screenshots/411f98a583916a41142c40294fd2ee00.png

但在我看来,这段代码 - 很糟糕!