2014-06-15 108 views
5

我想知道处理嵌套mysql-queries的最佳方式是nodejs。节点Mysql异步多重查询

因此,像这样:

connection.query("SELECT * FROM blogs ORDER BY time DESC", function(err, blogs, fields) { 

    for (blog in blogs) { 

     connection.query("SELECT * FROM tags WHERE blog_id='blog.id' ", function(err, tags, fields) { 

     blog.tags = tags 

    }); 

    } 

    res.send(blogs) 

}); 

这显然不起作用,因为的异步性质。在获取标签之前结果已经返回。

我一直在阅读节点和回调和承诺似乎是要走的路。但是我无法看到我在这个小例子中如何最好地使用它们。

Thx!

+0

这将是一个很好的机会开始使用像[Q](https://github.com/kriskowal/q)这样的承诺库,在这种情况下它是['Q.spread']( https://github.com/kriskowal/q#combination)方法(或者[这些简化示例](https://github.com/kriskowal/q#sequences) – Bojangles

回答

3

因此,您必须等待所有回调才能返回,然后再发送回复。如果我们忽略的错误处理和简单空结果可以做到这一点类似于:

var callback = function(blogs) { 
    res.send(blogs); 
} 

connection.query("SELECT * FROM blogs ORDER BY time DESC", function(err, blogs, fields) { 
    var pending = blogs.length; 

    for (blog in blogs) { 

     connection.query("SELECT * FROM tags WHERE blog_id='blog.id' ", function(err, tags, fields) { 
     blog.tags = tags; 

     if (0 === --pending) { 
      callback(blogs); 
     } 
    }); 
    } 
}); 

有了承诺,看看Promise.all函数返回一个新的承诺。当所有承诺传递给阵列时,这个承诺就解决了。用Q库应该是这样的:

var getTags = function(blog) { 
    var deferred = Q.defer(); 
    connection.query("SELECT * FROM tags WHERE blog_id='blog.id' ", function(err, tags, fields) { 
     blog.tags = tags; 
     deferred.resolve(); 
    }); 
    return deferred.promise; 
} 

var promises = blogs.map(getTags(blog)); 

Q.all(promises).then(res.send(blogs)); 
2

你可以尝试这样的事情;

​​

希望这会有所帮助。

+0

为什么这个答案downvoted?我同意这个问题的理想解决方案是在单个查询中获取这两个数据。如果需要两个查询,这个解决方案就可以工作,这个片段还分享了一个简洁的方式来处理循环中的回调,而不使用async/promise /等流程控制库。 – vmx

3

您可以使用async.series模块的(在queries`迭代)

async.eachSeries(blogs, 
       function (query, callback) { 

        connection.query(blogs.blog, "SELECT * FROM tags WHERE blog_id='blog.id'" , function (err, result) { 
         if (err) { 

          //throw err; 
          callback(err, null); 
          return; 

         } else { 
          console.log('Query executed successfully'); 
          blogs.blog.tags = tags; 
         } 
         callback(null, blogs.blog); 

        }); 

       }, 

       function finalCallback(err, results) { 

          return callback(null, results); 
         }); 
        } 
       }); 

     }); 



    });` 

你可以用和query.on功能加强这方面的(以处理每一行)