Async.jsシリーズ内のGETメソッドとCouchDB操作が複数回以上実行されていないループの場合

StackOverflow https://stackoverflow.com//questions/22073762

質問

async.jsシリーズを使用して連続してhttpを取得しています。まず、APIクエリからの数の結果を検索してから、各結果について別のクエリを実行します。結果は配列に格納され、次にCouchDBデータベースに保存されます。結果の数は200に制限されているので、私はこれを複数回実行する必要があります(したがって、for Loop)。コードの基本構造は以下の通りです(下記のフルコード)

for (...) {
  async.series(
     [
       function(){ http get method }, 
       function (){ async.eachSeries(){ http get method }, callback function }
     ],
     function(){ database operations }
  );//end series
}//end for loop
.

私の問題は、ループが一度だけ実行されることです。ループ内のすべてが予想どおりに機能し、データはデータベースに正しく保存されます。ただし、ループが再度実行されない理由を理解できません。私は私がAsyncコールバック関数でメソッド呼び出しをするかどうかを知っています。For Loopはコールスタックにあるはずだと思います。したがって、非同期が行われると、ループは単に続行する必要がありますが、これは明らかにそうではありません。

フルコード:

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
.

役に立ちましたか?

解決

大丈夫、私はついにそれを解決しました。ループが同期的に実行されていないことが判明したため、ASYNCシリーズ内部のループ条件付き(ELSVR_COUNT)を更新するため、条件付きが正しく設定される前にループが終了しました。ただし、それは唯一の問題ではありませんでした - その条件付きアップデートを削除し、単にelsvr_countをループの外側の多数の数に設定すると、ASYNCシリーズが返される前にループは非同期的に実行されます。

他の人が同様の問題に遭遇した場合に私の解決策を投稿します。基本的にはforループを非同期に置き換えます.Whilstループ

        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
.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top