对于具有GET方法的循环和async.js系列中的CouchDB操作不执行多次

时间:2014-02-27 15:59:30

标签: javascript asynchronous get couchdb async.js

我使用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

1 个答案:

答案 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