我使用async.js系列进行连续的http get调用,所有这些都在for循环中。首先,我从API查询中检索大量结果,然后对每个结果运行另一个查询。结果存储在一个数组中,然后保存到CouchDB数据库中。因为结果的数量限制为200,所以我必须多次这样做(因此for循环)。代码的基本结构如下(下面的完整代码)
for (...) {
async.series(
[
function(){ http get method },
function (){ async.eachSeries(){ http get method }, callback function }
],
function(){ database operations }
);//end series
}//end for loop
我的问题是循环只执行一次。循环内的所有内容都按预期工作,数据正确保存到数据库中 - 但我无法弄清楚为什么循环不会再次运行。我知道如果我在异步回调函数中放置一个方法调用它会运行正常,所以也许我错过了有关异步如何工作的一些东西。我认为for循环应该在调用堆栈上,所以当异步完成时,循环应该继续,但显然情况并非如此。
完整代码:
for (var retstart = 0; retstart < elsvr_count; retstart += elsvr_retSize) {
var elsvr_resultChunk;
async.series(
[
function(callback){
var elsvr_Query = String(elsvr_baseURL) + "apiKey="+ String(elsvr_apiKey) + "&query=af-id(" + String(elsvr_ID) + ")&httpAccept=application/" + String(elsvr_resultType) + "&count=" + String(elsvr_retSize) + "&view=";
$.get(elsvr_Query, function(result) {
elsvr_count = parseInt(result["search-results"]["opensearch:totalResults"]); //the number of results
console.log("count set at " + elsvr_count);
elsvr_resultChunk = result["search-results"]["entry"]; //the current chunk of the total result, the size of which elsvr_retSize
callback(null);
});//end get
},
function(callback){
async.eachSeries(elsvr_resultChunk, function(item, callback){
var docQuery = item["prism:url"] + "?apiKey=" + String(elsvr_apiKey) + "&httpAccept=application/" + String(elsvr_resultType);
$.ajax({
url: docQuery,
type: 'GET',
dataType: 'json',
success: function(result){
elsvr_results.push(result);
return callback(null);
},
error: function(err){
console.log("error returned: "+err.statusText);
elsvr_errors = elsvr_errors+1;
return callback(null);
}
});
},
function(err, results) {
if (err) console.log("error: " + err);
else
callback(null, elsvr_results);
});
}
],
//callback from async.series
function (err, results){
if (err)
console.log("ERROR: " + JSON.stringify(err));
else {
db.getDoc('unprocessed', function(er, doc){
if (er) throw new Error(JSON.stringify(er));
if (doc.elsvr != undefined)
doc.elsvr = _.extend(results[1], doc.elsvr);
else
doc.elsvr = results[1];
db.saveDoc('unprocessed', doc, function(er, ok) {
if (er) throw new Error(JSON.stringify(er));
console.log('saved a chunk to the database: ' + db.name);
});
});
}
}
);//end async.series
}//end for loop
答案 0 :(得分:0)
好的,我终于解决了。结果是循环没有同步执行,并且因为我更新了异步系列中的循环条件(elsvr_count),所以循环在条件实际设置正确之前完成。但是,这不是唯一的问题 - 如果我删除了条件更新并简单地将elsvr_count设置为循环外的高数字,则循环仍然会在异步系列返回之前异步运行。
我会发布我的解决方案以防其他人遇到类似的问题:基本上,用async.whilst循环替换for循环如下
async.whilst(function() { return retstart < elsvr_count; },
function(callback) {
var elsvr_resultChunk;
async.series(
//...
//same stuff as above goes here
//...
//save the document to the database
db.saveDoc('unprocessed', doc, function(er, ok) {
if (er) throw new Error(JSON.stringify(er));
retstart += elsvr_retSize; //<-- to replace the increment of the for loop
callback(null); //<-- important
});
//...
//...
);//end async.series
},
//callback for the whilst loop. this will be called once the condition is no longer met (retstart < elsvr_retSize)
function(err) {
//do stuff in here
}
);//end async.whilst