async for node.js中的循环

我是新来的这个node.js ..我对这个callback有点困惑..在我的应用程序里面一个for循环我打电话给一个asynchronous函数调用,我想我的问题是,在我得到asynchronous调用的响应之前我的for循环得到循环。

我的代码:

async.forEach(Object.keys(config), function(key, next) { search(config[key].query, function(err, result) { // console.log("fffffffffff="+ util.inspect(result))-------- >>>Getting undefined.. if (err) return next(err) // var json = JSON.stringify({ "result": result }); results[key] = { "result": result } console.log("rrrrrrrr="+util.inspect(results[key])) next() // <---- critical piece. This is how the forEach knows to continue to the next loop. Must be called inside search's callback so that it doesn't loop prematurely. }) }, function(err) { console.log('iterating done'); res.writeHead(200, { 'content-type': 'application/json' }); res.end(JSON.stringify(results)); }); } 

searchfunction代码:

 var matches = []; var qrySubString = query.substring(0, 4); client.query("select * from xxxxxxxxx where level4 ILIKE '%" + query + "%'", function(err, row1, fields) { for (var id in row1.rows) { var match, name; if (query == row1.rows[id].level4) { match = true; name = row1.rows[id].level4; } else { match = false; name = query; } matches.push({ "id": id, "name": row1.rows[id].level4, "score": 100, "match": match, "type": [{ "id": "/people/presidents", "name": "US President" }] }) } callback(matches); }) 

我想成功执行1searchfunction后执行for循环,我想我必须使用async for循环。请指导我解决此问题。

我已经将您的代码示例简化为以下几行,以便更容易理解概念的解释。

 var results = []; var config = JSON.parse(queries); for (var key in config) { var query = config[key].query; search(query, function(result) { results.push(result); }); } res.writeHead( ... ); res.end(results); 

前面的代码的问题是searchfunction是asynchronous的,所以当循环结束时,没有任何callback函数被调用。 因此, results列表是空的。

为了解决这个问题,你必须把代码放在callback函数的循环之后。

  search(query, function(result) { results.push(result); // Put res.writeHead( ... ) and res.end(results) here }); 

但是,由于callback函数被多次调用(每次迭代一次),您需要知道所有的callback函数都被调用了。 为此,您需要计算callback数量,并检查该数字是否等于asynchronous函数调用的数量。

要获取所有键的列表,请使用Object.keys 。 然后,遍历这个列表,我使用.forEach (你也可以使用for (var i = 0, key = keys[i]; i < keys.length; ++i) { .. }问题,请参阅循环中的JavaScript闭包 – 简单的实例 )。

这是一个完整的例子:

 var results = []; var config = JSON.parse(queries); var onComplete = function() { res.writeHead( ... ); res.end(results); }; var keys = Object.keys(config); var tasksToGo = keys.length; if (tasksToGo === 0) { onComplete(); } else { // There is at least one element, so the callback will be called. keys.forEach(function(key) { var query = config[key].query; search(query, function(result) { results.push(result); if (--tasksToGo === 0) { // No tasks left, good to go onComplete(); } }); }); } 

注意:上例中的asynchronous代码是并行执行的。 如果函数需要以特定顺序调用,那么可以使用recursion来获得所需的效果:

 var results = []; var config = JSON.parse(queries); var keys = Object.keys(config); (function next(index) { if (index === keys.length) { // No items left res.writeHead( ... ); res.end(results); return; } var key = keys[index]; var query = config[key].query; search(query, function(result) { results.push(result); next(index + 1); }); })(0); 

我所展示的是这些概念,您可以在实现中使用许多(第三方)NodeJS模块之一,例如async 。

你已经正确地诊断了你的问题,这么好的工作。 一旦你调用你的search代码,for循环就保持正确。

我是https://github.com/caolan/async的忠实粉丝,这对我很好&#x3002; 基本上,你会得到像这样的东西:

 var async = require('async') async.eachSeries(Object.keys(config), function (key, next){ search(config[key].query, function(err, result) { // <----- I added an err here if (err) return next(err) // <---- don't keep going if there was an error var json = JSON.stringify({ "result": result }); results[key] = { "result": result } next() /* <---- critical piece. This is how the forEach knows to continue to the next loop. Must be called inside search's callback so that it doesn't loop prematurely.*/ }) }, function(err) { console.log('iterating done'); }); 

我希望有帮助!

我喜欢在这种情况下使用recursion模式。 例如,像这样的东西:

 // If config is an array of queries var config = JSON.parse(queries.querrryArray); // Array of results var results; processQueries(config); function processQueries(queries) { var searchQuery; if (queries.length == 0) { // All queries complete res.writeHead(200, {'content-type': 'application/json'}); res.end(JSON.stringify({results: results})); return; } searchQuery = queries.pop(); search(searchQuery, function(result) { results.push(JSON.stringify({result: result}); processQueries(); }); } 

processQueries是一个recursion函数,它将从查询数组中抽出查询元素进行处理。 然后,当查询完成时,callback函数再次调用processQueriesprocessQueries知道在没有查询时结束。

使用数组来完成这个操作是最简单的,但是可以修改它来处理我想象中的对象键/值。

Node.js引入的async await7.6 async await ,所以这使得Javascript更漂亮。

 var results = []; var config = JSON.parse(queries); for (var key in config) { var query = config[key].query; results.push(await search(query)); } res.writeHead( ... ); res.end(results); 

为了这个工作searchfunction必须返回一个promise或它必须是asyncfunction

如果它没有返回一个Promise你可以帮助它返回一个Promise

 function asyncSearch(query) { return new Promise((resolve, reject) => { search(query,(result)=>{ resolve(result); }) }) } 

然后replace这一行await search(query); 通过await asyncSearch(query);