【问题标题】:For loop with GET methods and CouchDB operations inside async.js series not executing more than once在 async.js 系列中使用 GET 方法和 CouchDB 操作的 for 循环不会执行多次
【发布时间】:2014-02-27 15:59:29
【问题描述】:

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

【问题讨论】:

    标签: javascript asynchronous get couchdb async.js


    【解决方案1】:

    好的,我终于解决了。结果发现循环没有同步执行,并且由于我在异步系列中更新了循环条件(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
    

    【讨论】:

      猜你喜欢
      • 2013-06-09
      • 1970-01-01
      • 2022-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-11
      • 2015-01-28
      相关资源
      最近更新 更多