我已经使用async.waterfall来压缩嵌套函数,如下所示。
function convertPortfolio(trademarks, fn){
async.waterfall([function(callback){
groupByCountry(trademarks, callback)
},
function(TMsGroupedByCountry, callback){
addEUTrademarks(TMsGroupedByCountry['EU'], TMsGroupedByCountry, callback)
},
function(revisedGroupByCountry, callback){
groupTrademarksByStatus(revisedGroupByCountry, callback)
}], function(err, splitByStatus){
fn(null, splitByStatus);
})
}
嵌套替代
function convertPortfolio(trademarks, fn){
groupByCountry(trademarks, function(err, TMsGroupedByCountry){
addEUTrademarks(TMsGroupedByCountry['EU'], TMsGroupedByCountry, function(err, revisedGroupByCountry){
groupTrademarksByStatus(revisedGroupByCountry, function(err, splitByStatus){
fn(null, splitByStatus)
});
});
});
}
随后当我将此函数作为另一个函数的一部分调用时,它完美地运行。但是当我尝试使用来自阵列上的forEach调用的单独值多次调用该函数时,当嵌套版本工作正常时,它无法工作。我无法解释为什么会出现这种情况,并且说实话,我不知道从哪里开始。我的理解是forEach调用应该只是意味着相应地处理每个单独的值并关闭,所以这不应该是问题。
异步功能正常工作并在此实例中返回值
exports.convertPortfolioAndAddToGeoJSON = function(geojson, trademarks, fn){
convertPortfolio(trademarks, function(err, revisedTMs){
addToGeoJson(geojson, revisedTMs, function(err, gj){
fn(null, gj)
});
});
}
但是在这种情况下,未填充结束目标对象:
exports.convertYearPortfolioAndAddToGeoJSON = function(geojson, trademarks, fn){
var target = {};
Object.keys(trademarks).forEach(function(year){
convertPortfolio(trademarks[year], function(err, revisedTMs){
addToGeoJson(geojson, revisedTMs, function(err, revisedGeoJSON){
target[year] = revisedGeoJSON;
});
});
});
fn(null, target);
}
在某些点使用console.log显示在嵌套示例中,在记录目标对象之前记录返回值,而使用async.waterfall示例时,在返回的数据可用之前记录目标对象(所以我认为记录目标导致空对象并不奇怪)。
我认为在每种情况下都存在回调,这意味着目标的记录只会在所有先前的处理完成后才会发生,但是虽然这似乎是嵌套替代的情况,但事实并非如此至少在多次调用时使用异步版本。
任何指导都将不胜感激。
更新出于兴趣,这里使用async.forEach修改了代码:
exports.convertYearPortfolioAndAddToGeoJSON = function(geojson, trademarks, fn){
var target = {};
async.forEach(Object.keys(trademarks), function(year, callback){
async.waterfall([
async.apply(convertPortfolio, trademarks[year]),
function(revisedTMs, callback){
addToGeoJson(geojson, revisedTMs, callback)
}],
function(err, revisedGeoJSON){
target[year] = revisedGeoJSON;
callback()
})
}, function(err){
fn(null, target);
});
}
答案 0 :(得分:1)
Object.keys(trademarks).forEach
是同步的,无法正确跟踪闭包/范围。您需要在那里使用async.forEach(Object.keys(trademarks), function(year, callback)....
,并相应地调整异步控制流。
当你使用这个带有微小包装函数的模式时,也就是FYI:
function convertPortfolio(trademarks, fn){
async.waterfall([function(callback){
groupByCountry(trademarks, callback)
},
您可以使用async.apply
作为该样板:
function convertPortfolio(trademarks, fn){
async.waterfall([async.apply(groupByCountry, trademarks),
...