Para loop com os métodos GET e o CouchDB operações dentro async.js a série não executar mais de uma vez
-
23-12-2019 - |
Pergunta
Eu estou fazendo consecutivos http get chamadas usando async.js a série, que é dentro de um loop for.Primeiro eu obter um número de resultados de uma consulta da API, então eu executar outra consulta em cada um dos resultados.Os resultados são armazenados em uma matriz e, em seguida, salva um banco de dados CouchDB.Porque o número de resultados é limitado a 200, eu tenho que fazer isso várias vezes (daí o loop for).A estrutura básica do código é o seguinte (código completo abaixo)
for (...) {
async.series(
[
function(){ http get method },
function (){ async.eachSeries(){ http get method }, callback function }
],
function(){ database operations }
);//end series
}//end for loop
O meu problema é que o loop é executado apenas uma vez.Tudo dentro do loop funciona como esperado, e os dados são salvos corretamente o banco de dados--mas eu não consigo descobrir por que o loop não será executado novamente.Eu sei que se eu colocar uma chamada de método em função de retorno de chamada assíncrono ele vai funcionar bem, assim, talvez eu estou faltando alguma coisa sobre como assíncrono obras.Eu acho que o loop deve ser a pilha de chamadas, então, quando assíncrono é feito, o ciclo deve continuar, mas isso obviamente não é o caso.
Código completo:
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
Solução
Ok, eu finalmente resolvido.Acontece que o loop foi não executar de forma síncrona, e desde que eu atualizar o loop condicional (elsvr_count) dentro da série assíncrona, o ciclo foi concluído antes da condicional, na verdade, foi definido corretamente.No entanto, esse não era o único problema--se eu removido condicionais atualização e simplesmente definir elsvr_count ser um número alto, fora do loop, o loop seria ainda antes de executar de forma assíncrona assíncrona série devolvidos.
Eu vou postar a minha solução no caso de qualquer outra pessoa, é executado em um problema semelhante:Basicamente, substituir o loop for com um assíncrono.enquanto o ciclo da seguinte forma
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