首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >node-mysql计时

node-mysql计时
EN

Stack Overflow用户
提问于 2012-06-14 00:08:52
回答 3查看 201关注 0票数 3

我有一个这样的递归查询(注意:这只是一个示例):

代码语言:javascript
复制
var user = function(data)
{
  this.minions = [];
  this.loadMinions = function()
  {
    _user = this;
    database.query('select * from users where owner='+data.id,function(err,result,fields)
    {
      for(var m in result)
      {
        _user.minions[result[m].id] = new user(result[m]); 
        _user.minions[result[m].id].loadMinions();
      }
    }  
    console.log("loaded all minions");
  }
}
 currentUser = new user(ID);
 for (var m in currentUser.minions)
 {
   console.log("minion found!");
 }

这不起作用,因为timmings都是错误的,代码不会等待查询。

我试过这样做:

代码语言:javascript
复制
var MyQuery = function(QueryString){
    var Data;
    var Done = false;
    database.query(QueryString, function(err, result, fields) { 
        Data = result;
        Done = true;
    });
    while(Done != true){};
    return Data;
}

var user = function(data)
{
  this.minions = [];
  this.loadMinions = function()
  {
    _user = this;
    result= MyQuery('select * from users where owner='+data.id);
    for(var m in result)
    {
      _user.minions[result[m].id] = new user(result[m]); 
      _user.minions[result[m].id].loadMinions();
    }
    console.log("loaded all minions");
  }
}
currentUser = new user(ID);
for (var m in currentUser.minions)
{
  console.log("minion found!");
}

但他只是在这段时间僵住了,我是不是错过了什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-06-14 00:53:25

解决问题的第一个障碍是理解Node.js中的I/O是异步的。一旦您知道如何将其应用于您的问题,递归部分将变得容易得多(特别是如果您使用诸如Async或Step之类的流控制库)。

这里有一个例子,它完成了你想要做的一些事情(去掉了递归)。就我个人而言,我会避免像这样递归加载可能未知数量/深度的记录;而是按需加载它们,如下例所示:

代码语言:javascript
复制
var User = function(data) {
    this.data = data
    this.minions;
};

User.prototype.getMinions = function(primaryCallback) {
    var that = this; // scope handle
    if(this.minions) { // bypass the db query if results cached
        return primaryCallback(null, this.minions);
    }

    // Callback invoked by database.query when it has the records
    var aCallback = function(error, results, fields) {
        if(error) {
            return primaryCallback(error);
        }

        // This is where you would put your recursive minion initialization
        // The problem you are going to have is callback counting, using a library
        // like async or step would make this party much much easier

        that.minions = results; // bypass the db query after this
        primaryCallback(null, results);
    }

    database.query('SELECT * FROM users WHERE owner = ' + data.id, aCallback);
};

var user = new User(someData);    
user.getMinions(function(error, minions) {
    if(error) {
        throw error;
    }

    // Inside the function invoked by primaryCallback(...)
    minions.forEach(function(minion) {
        console.log('found this minion:', minion);
    });
});

在这个例子中最需要注意的是回调。database.query(...)是异步的,您不希望在等待它完成时阻塞事件循环。这可以通过向查询提供一个回调aCallback来解决,该回调将在结果准备就绪时执行。一旦触发了该回调,并且在对记录执行了想要执行的任何处理之后,就可以使用最终结果触发primaryCallback

票数 2
EN

Stack Overflow用户

发布于 2012-06-14 00:26:36

每个Node.js进程都是单线程的,所以代码行

代码语言:javascript
复制
while(Done != true){};

接管线程,并且本应将Done设置为true的回调永远不会运行,因为线程头在无限循环中被阻塞。

您需要重构程序,以便将依赖于查询结果的代码包含在回调本身中。例如,让MyQuery接受一个回调参数:

代码语言:javascript
复制
MyQuery = function(QueryString, callback){

然后在database.query回调的末尾调用回调--甚至将其作为database.query回调提供。

票数 2
EN

Stack Overflow用户

发布于 2012-06-14 00:28:05

不幸的是,冻结是正确的行为,因为Node是单线程的。

您需要一个调度程序包来修复此问题。就我个人而言,我一直在使用Fibers-promise来解决这类问题。您可能想要查看此或其他promise库或async

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11018998

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档