重新编码嵌套for循环在node.js中使用asynchronous

我是新的Node.js和asynchronous编码。 我需要编写一个嵌套的for循环,这将与Node一起使用。 我知道我的问题与这里发布的问题非常相似: 在nodejs中以asynchronous方式嵌套循环,下一个循环必须在完成后才能启动 ,但即使详细查看该post后,我也无法修复我的代码。

我正在使用XML Feed。 “parsing器”使用xml2js包。 如果我删除sql查询(为此我使用的是mysql节点包),但是当我把sql查询放入时,所有的订单首先被处理,输出“DONE”然后查询失败,因为它试图重复查找最后一个订单的项目。

我试过用async.forEach循环replacefor循环,但这没有帮助。

任何帮助或build议,如何重新编码这种方式更加惯用的节点将不胜感激。

非常感谢! Sixhobbits

parser.parseString(data, function (err, result) { if(err) throw(err); var numOrders = result['Root']['Orders'][0]['Order'].length; var curr, currItem, currOrdId, items, sellersCode; console.log("Logging IDs of", numOrders, "orders"); // for each order for (var j=0; j<numOrders; j++){ //current order curr = result['Root']['Orders'][0]['Order'][j]; currOrdId = curr['OrderId'][0] items = curr['Items'][0]['Item']; console.log("Order ID:", currOrdId, "--",items.length, "Items"); // for each item for (var k=0; k<items.length; k++){ currItem = items[k]; sellersCode = currItem['SellersProductCode'][0]; var sqlQuery = 'select data_index, fulltext_id, cataloginventory_stock_item.product_id from catalogsearch_fulltext inner join cataloginventory_stock_item where catalogsearch_fulltext.data_index like "' + sellersCode + '|%"' + 'and cataloginventory_stock_item.item_id = catalogsearch_fulltext.product_id'; var query = connection.query(sqlQuery,function(err,rows,fields){ if (err) throw(err); console.log(" Item ID :",currItem['ItemId'][0]); console.log(" Full Text ID :", rows[0]['fulltext_id']); console.log(" Product ID :", rows[0]['product_id']); }); }//for }//for console.log("DONE"); });//parseString 

你正在寻找使用async.forEach在正确的轨道上。 以下是您将如何重写此代码以使用该代码:

 parser.parseString(data, function (err, result) { if(err) throw(err); var numOrders = result['Root']['Orders'][0]['Order'].length; var currOrdId, items, sellersCode; console.log("Logging IDs of", numOrders, "orders"); // for each order async.forEach(result['Root']['Orders'][0]['Order'], function (curr, callback1) { currOrdId = curr['OrderId'][0]; items = curr['Items'][0]['Item']; console.log("Order ID:", currOrdId, "--",items.length, "Items"); async.forEach(items, function (currItem, callback2) { sellersCode = currItem['SellersProductCode'][0]; var sqlQuery = 'select data_index, fulltext_id, cataloginventory_stock_item.product_id from catalogsearch_fulltext inner join cataloginventory_stock_item where catalogsearch_fulltext.data_index like "' + sellersCode + '|%"' + 'and cataloginventory_stock_item.item_id = catalogsearch_fulltext.product_id'; var query = connection.query(sqlQuery,function(err,rows,fields){ console.log(" Item ID :",currItem['ItemId'][0]); console.log(" Full Text ID :", rows[0]['fulltext_id']); console.log(" Product ID :", rows[0]['product_id']); callback2(err); }); }, callback1); }, function (err) { console.log("DONE"); }); });//parseString 

async.forEach每次迭代必须在其所有asynchronous处理完成时调用其callback参数。 在这种情况下,你有两个层面,这使得追踪你的头脑变得更加困难,但这是相同的概念。

这是一个典型的闭环问题。 您需要通过将currItem作为参数来打破closures:

  for (var k=0; k<items.length; k++){ currItem = items[k]; sellersCode = currItem['SellersProductCode'][0]; var sqlQuery = 'select data_index, fulltext_id, cataloginventory_stock_item.product_id from catalogsearch_fulltext inner join cataloginventory_stock_item where catalogsearch_fulltext.data_index like "' + sellersCode + '|%"' + 'and cataloginventory_stock_item.item_id = catalogsearch_fulltext.product_id'; var query = connection.query(sqlQuery,(function(CI){ return function(err,rows,fields){ if (err) throw(err); console.log(" Item ID :",CI['ItemId'][0]); console.log(" Full Text ID :", rows[0]['fulltext_id']); console.log(" Product ID :", rows[0]['product_id']); } })(currItem)); // Break closure by passing currItem as argument }//for 

我意识到这是一个旧的post,但你可能会觉得这个function很有用

 eachKVAsync = function(elements,userInfo,onKeyValue,ondone) { var onDone = ondone; var ret = null; var done=false; var isArray = typeof elements.forEach===$f$; var keys = isArray ? null : [], values = isArray ? elements : []; if (keys) { for (var k in elements) { keys.push(k); values.push(elements[k]); } } var aborted=false; var endLoop = function (userInfo){ aborted=true; if (onDone) { onDone(userInfo,aborted); onDone = null; } } var i = 0; var iterate = function (userInfo) { if (i < values.length) { var ix=i; i++; onKeyValue((keys?keys[ix]:i),values[ix],userInfo,iterate,endLoop); } else { if (onDone) { onDone(userInfo,aborted); onDone = null; return; } } } iterate(userInfo); }, 

使用示例

  eachKVAsync( elements, { aValue: 2004 }, function onItem(key, value, info, nextItem, endLoop) { if (value.isOk) { info.aValue += value.total; setTimeout(nextItem,1000,info); } else { endLoop(info); } }, function afterLastItem(info, loopEndedEarly) { if (!loopEndedEarly) { console.log(info.aValue); } } );