2012-06-03 72 views
8

我的node.js腳本從數據庫1中的表中讀取行,執行一些處理並將行寫入數據庫2中。什麼是在「完成所有事情」後退出node.js腳本的好方法

腳本應該在完成所有事情後退出。

我怎麼知道一切是否完成並退出節點呢?

如果我有這樣一個回調函數:

function exit_node() { 
    process.exit(); 
} 

(編輯:在此期間,它變得越來越明顯,process.exit()也可以替換爲db.close() - 但這不是問題是在什麼時候準確地做到這一點,即如何以及在哪裏執行此回調。)

但是,將它附加到某處並不容易。在最後一次從db1中讀取之後不正確,因爲處理和寫入仍然必須發生。

將它附加到寫入db2並不容易,因爲它必須在最後一次寫入後進行連接,但每次寫入都是獨立的,並且不知道它是否是最後一次寫入。

它也可能理論上發生,最後寫入完成,但在此之前的另一個寫入仍在執行。


編輯:對不起,我可以看到這個問題的解釋是不完整的,可能令人困惑,但還是有人理解並有如下好的答案。請繼續閱讀評論和答案,它應該給你全貌。


編輯:我可以想到一些「阻塞」控制器機制。腳本的不同部分爲每個打開的「作業」向控制器添加阻止程序,並在作業完成後釋放它們,並且當沒有更多的作業程序存在時,控制器退出腳本。也許異步可以幫助:https://github.com/caolan/async

我也擔心這會炸燬代碼和邏輯不合理。

+0

我不明白你的問題。當所有事情完成後,Node *都會退出。一旦沒有更多的異步調用正在進行 - 一旦你完成了你讀的最後一條記錄的處理,並且所有的寫操作都已經完成 - 那麼Node將自行退出;你不必做任何特別的事情。 –

+6

@JoeWhite許多數據庫模塊將保持打開一個連接,保持進程運行。我認爲這個問題(糾正我,如果我錯了,SHernandez)是如何知道節點何時完成與數據庫相關的所有異步IO,以便他知道何時關閉數據庫連接以允許進程退出。 –

+2

節點將不會退出,直到有一個或多個回調等待或事件發射器處於活動狀態。正如@BrandonTilley提到的,一些DB模塊保持DB連接打開(即EventEmitter),所以在完成查詢後應該關閉它。因此,在查詢的回調函數中寫入'db.close'(參見文檔),處理結果和節點將自行退出(不調用'process.exit')。 – elmigranto

回答

3

雖然使用計數器可能會很誘人(簡單,易實現的想法),然後退出,它會污染與邏輯無關的代碼。

db1.query(selector, function(err, results) { 
    db1.close(); 

    // let's suppose callback gets array of results; 
    // once all writes are finished, `db2.close` will be called by async 
    async.forEach(results, processRow, db2.close); 
}); 

// async iterator 
function processRow(row, cb) { 
    // modify row somehow 
    var newRow = foo(row); 

    // insert it in another db; 
    // once write is done, call `cb` to notify async 
    db2.insert(newRow, cb); 
} 

雖然使用process.exit這裏感覺就像C++ new沒有delete我。不好對比也許吧,但是忍不住吧:)

+0

選擇器代表什麼? (db1.query的第一個參數)? – SHernandez

+0

@SHernandez你**不知何故選擇**行,對吧?如果是Postgres,'selector'將是一個字符串('SELECT now();'或其他)。如果是其他數據庫,則選擇器將是其他數據庫。插入時用'newRow'也是一樣。無論如何,這是我的答案中的一個想法,而不是真正的代碼。 – elmigranto

7

兩個主要選項是:

  1. 使用異步處理協調模塊像async(如你所提到的)。
  2. 保持自己出色的寫入次數,當計數數達到0.1
+0

我喜歡沒有2.它應該不是一個問題增加和減少從不同的回調例程並行的同一個全局計數器?增加和減少可以隨時從應用程序的不同部分發生,我可以在節點中執行此操作嗎? – SHernandez

+0

當處理異步時,爭用沒有問題,它仍然是單線程的。 – JohnnyHK

+0

@SHernandez節點本身沒有任何東西是平行的。在整個項目中沒有兩行代碼,可以同時運行。所以,不需要訪問序列化。 – elmigranto

10

JohnnyHK給出了很好的建議;除了Node.js已經爲你做了選項2。

當沒有更多I/O,定時器,間隔等(預計不再需要工作)時,該過程將退出。如果你的程序在所有工作完成後不能自動退出,那麼你有一個錯誤。也許你忘了關閉數據庫連接,或者到clearTimeout()clearInterval()。但是不要打電話給process.exit(),您可以藉此機會確定您的泄漏情況。

+0

JasonSmith,這是相反的,我試圖在問題中解釋。因爲我使用回調,他們都不知道哪一個是最後一個。只要我知道,什麼時候完成,我可以關閉數據庫連接或退出或其他任何事情。但是這首先是我的問題的原因。 – SHernandez

+2

這就是:),謝謝,'如果你的程序在所有工作完成後都不會自動退出,那麼你有一個bug' – Rabea

相關問題