2014-06-15 50 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功能加強這方面的(以處理每一行)