2012-01-13 48 views
2

如何在另一個異步each方法(NodeJS)內部進行異步方法調用?如何在另一個異步`each`方法(NodeJS)內部進行異步方法調用?

具體示例 - 使用數據庫,我需要刪除所有記錄。 但我不能只刪掉整個集合,我需要逐一銷燬每條記錄,在刪除之前我需要讀取記錄,在應用程序中執行一些業務邏輯,然後刪除它。

所以,讓我們嘗試實現我們deleteAll方法(實際上它是從節點MongoDB的原生驅動一個真正的API):

deleteAll = function(selector, callback){ 
    collection.find(selector).each(function(err, doc){ 
    if(err){ 
     callback(err) 
    }else{ 
     if(doc === null){ 
     // each returns null when there's no more documents, we are finished. 
     callback(null)  
     }else{ 
     doSomeBusinessLogicBeforeDelete(doc) 

     // How to delete it using asynchronous `remove` method?   
     collection.remove({_id: doc._id}, function(err){ 
      // What to do with this callback? 
      // And how to make `each` wait untill we 
      // deleting this record? 
      ??? 
     }) 
     }  
    } 
    }) 
} 

有實際上是一個辦法做到這一點 - 使用collection.nextObject方法而不是collection.each ,但我想知道是否有可能使用each解決這個問題?現在我相信這是不可能的,但也許我錯了?

UPDATE:each方法的來源:

Cursor.prototype.each = function(callback) { 
    var self = this; 

    if (!callback) { 
    throw new Error('callback is mandatory'); 
    } 

    if(this.state != Cursor.CLOSED) { 
    process.nextTick(function(){ 
     // Fetch the next object until there is no more objects 
     self.nextObject(function(err, item) {   
     if(err != null) return callback(err, null); 

     if(item != null) { 
      callback(null, item); 
      self.each(callback); 
     } else { 
      // Close the cursor if done 
      self.state = Cursor.CLOSED; 
      callback(err, null); 
     } 

     item = null; 
     }); 
    }); 
    } else { 
    callback(new Error("Cursor is closed"), null); 
    } 
}; 
+0

你有'each'方法的源代碼嗎?如果你有這個問題,應該很容易找到你。 – hugomg 2012-01-13 16:54:09

回答

0

那麼你寫了什麼工作,雖然不知道這行:

if(doc === null){ 
    // each returns null when there's no more documents, we are finished. 
    callback(null) 

因爲,我不知道這個邏輯,但那會起作用。從技術上講,函數不會等待,只需傳遞另一個函數,該函數將在工作完成時執行。這裏所做的是異步並行的。您還可以查看async模塊中的每個和其他某些功能的異步版本。

+0

嗯,是的,它是有點作品,但'collection.remove'將被並行執行而不是串行執行,並且最終的回調可能會在某些'collection.remove'完成之前觸發。 – 2012-01-13 17:23:15

1

嘗試類似這樣的事情。

deleteAll = function(selector, callback){ 
    // count all documents you need to fire remove for 
    var count = collection.filter(function(doc) { return doc === null }).length, 
      i = count; 

    collection.find(selector).each(function(err, doc){ 
    if(err){ 
     callback(err) 
    }else{ 
     if(doc === null){ 
     callback(null)  
     }else{ 
     doSomeBusinessLogicBeforeDelete(doc) 

     collection.remove({_id: doc._id}, function(err){ 
      i--; 
      if (i <= 0) callback('done'); 
     }) 
     }  
    } 
    }) 
} 
1

所以,一對夫妻帶着節點幾個月後,我得到了回答我的問題,這裏是一個可能實現的異步每個(可能還有其他的類似,但在錯誤處理細微差別):

​​

mongo中each的實現是不同的,它不可能用它做適當的順序迭代(也許它沒關係,也許他們有不同的設計目標)。