簡體   English   中英

Javascript for循環完成后如何執行代碼

[英]Javascript how to execute code after for loop completes

我正在嘗試解決這個js / async場景,並且想知道其他js世界如何處理此問題。

function doStuff(callback) {

  cursor.each(function(err, blahblah) {
    ...doing stuff here takes some time
  });

  ... Execute this code ONLY after the `cursor.each` loop is finished
  callback();

編輯

這是一個更具體的示例,使用下面的大多數建議進行了更新,但仍然無法使用。

function doStuff(callback) {

  MongoClient.connect(constants.mongoUrl, function(err, db) {

    var collection = db.collection('cases2');
    var cursor = collection.find();

    var promises = [];  // array for storing promises

    cursor.each(function(err, item) {

      console.log('inside each'); // NEVER GETS LOGGED UNLESS I COMMENT OUT THIS LINE: return Q.all(promises).then(callback(null, items));

      var def = Q.defer();        // Create deferred object and store
      promises.push(def.promise); // Its promise in the array

      if(item == null) {
        return def.resolve();
      }

      def.resolve();  // resolve the promise
    });

    console.log('items'); // ALWAYS GETS CALLED
    console.log(items);

    // IF I COMMENT THIS LINE OUT COMPLETELY, 
    // THE LOG STATEMENT INSIDE CURSOR.EACH ACTUALLY GETS LOGGED
    return Q.all(promises).then(callback(null, items));
  });
}

無需使用Promise或任何其他依賴項/庫,您只需

function doStuff(callback) {

添加一個櫃台

    var cursor = new Array(); // init with some array data
    var cursorTasks = cursor.length;

    function cursorTaskComplete()
    {
        cursorTasks--;

        if ( cursorTasks <= 0 ) {
            // this gets get called after each task reported to be complete
            callback();
        }
    }

    for ( var i = 0; i < cursor.length; i++ ) {
        ...doing stuff here takes some time and does some async stuff

在每個異步請求之后檢查

        ...when async operation is complete call
        cursorTaskComplete()
  }
}

在不知道您在cursor.each循環中進行異步調用的詳細信息的情況下,我將假定您有能力在每次調用的回調函數完成其異步任務時調用回調:

function doStuff() {
    var promises = [];  // array for storing promises

    cursor.each(function(err, blahblah) {
        var def = Q.defer();        // create deferred object and store
        promises.push(def.promise); // its promise in the array

        call_async_function(..., def.resolve);  // resolve the promise in the async function's callback
    });

    // pass the array to Q.all, only when all are resolved will "callback" be called
    return Q.all(promises);
} 

用法變為:

doStuff().then(callback)

請注意,回調的調用現在永遠不會觸及doStuff函數-該函數現在還返回一個promise。 您現在可以注冊多個回調,失敗回調等,而無需修改doStuff 這稱為“關注點分離”。

[NB:以上所有基於Q promises庫-https: //github.com/kriskowal/q]

EDIT的進一步討論和實驗已經確定.each調用本身是異步的,並且在看到最后一行時不向外界發出任何指示。 我創建了一個Gist ,它可以解決這個問題。

如果要使用async模塊執行此操作,則可以使用async forEachSeries函數

程式碼片段:

function doStuff(callback) {

  async.forEachSeries(cursor, function(cursorSingleObj,callbackFromForEach){
      //...do stuff which takes time
      //this callback is to tell when everything gets over execute the next function
      callbackFromForEach();
  },function(){
     //over here the execution of forEach gets over and then the main callback is called
    callback();
  });
}

在我看來,一個優雅/理想的解決方案是

 cursor.each(........).then( function() { ....your stuff});

但是沒有那個,你可以做到這一點。

http://plnkr.co/edit/27l7t5VLszBIW9eFW4Ip?p=預覽

其要旨如下所示。

var doStuff = function(callback) {
      cursor.forEach(function(cursorStep) {
        var deferred = $q.defer();
        var promise = deferred.promise;
        allMyAsyncPromises.push(promise);
        cursorStep.execFn(cursorStep.stepMeta);
        promise.resolve;
      });

      $q.when(allMyAsyncPromises).then(callback);
}

按下開始按鈕后,等待幾秒鍾...異步任務已模擬為在5秒鍾內完成,因此狀態將相應更新。

無法訪問真實的游標對象。.我不得不訴諸偽造的游標,如和數組。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM