2013-03-10 56 views
2

我有一個繁重的數據處理操作,需要按照10-12的simulatenous請求完成。我已經閱讀了更高級別的併發性Node.js是一個很好的平臺,它通過一個非阻塞事件循環來實現它。我知道,對於像查詢數據庫這樣的事情,我可以產生一個事件到一個單獨的進程(如mongod,mysqld),然後有一個回調來處理該進程的結果。很公平。如何在node.js中完成繁重的處理操作

但是如果我想要在回調中完成大量計算,該怎麼辦。它會阻止其他請求,直到該回調中的代碼完全執行。例如,我想處理一個高分辨率的圖像和代碼,我已經在Javascript本身(no separate進程做圖像處理)。

我想實現的方式是像

get_image_from_db(image_id, callback(imageBitMap) { 
    heavy_operation(imageBitMap); // Can take 5 seconds. 
}); 

將採取在這5秒中的任何請求heavy_operation停止節點。或者我正在考慮錯誤的方式來完成這樣的任務。請指導,我是JS新手。

UPDATE

或者也可以像我可以處理局部圖像,使事件循環回去採取其他回調並返回到處理該部分圖像。 (比如優先事件)。

回答

3

是的,它會阻止它,因爲回調函數在主循環中執行。它只是異步調用的函數,不會阻塞循環。這是我的理解,如果你想圖像處理異步執行,你將不得不使用一個單獨的進程來做到這一點。

請注意,您可以編寫自己的異步過程來處理它。開始你可以閱讀How to write asynchronous functions for Node.js的答案。

UPDATE

how do i create a non-blocking asynchronous function in node.js?也可能是值得一讀。這個問題實際上是在我鏈接的另一個引用的,但我想我會將它包括在這裏爲了簡單起見。

+0

但是,如果我有單獨的進程爲重操作,如果我說的有15個請求進來,會不會它創建15道工序。這將是非常昂貴的。我不喜歡在節點中創建線程。謝謝你的回答。我會接受它,一旦我得到我的懷疑清除:) – 2013-03-10 00:51:04

+0

也檢查我的問題中的更新。 – 2013-03-10 00:51:51

+1

是的,它會創建15個進程,並且據我所知,你不能在Node中創建線程。它有一個線程,這是您的主要事件循環。另一個選擇是編寫一個單獨的Node Worker應用程序,它的任務圖像處理通過消息隊列(RabbitMQ或其他)傳遞給它。然而,這隻會同步處理圖像(一次一個)。如果你想讓它們同時處理,你將不得不創建獨立的進程。 – 2013-03-10 00:59:26

3

很抱歉,我還沒有足夠的知名度對Nick的評論發表評論,但是你看看Node's cluster API?目前它仍然是實驗性的,但它可以讓你產生多個線程。

+0

+1感謝您的回答。將研究它:) – 2013-03-10 02:35:43

0

當在回調中完成大量計算時,事件循環將被阻塞,直到計算完成。這意味着回調會阻止事件循環5秒。

我的解決方案

有可能使用一臺發電機的功能,產生反饋控制事件循環。我將使用運行3秒的while loop作爲長時間運行的回調。

沒有發電機功能

let start = Date.now(); 

setInterval(() => console.log('resumed'), 500); 
function loop() { 
    while ((Date.now() - start) < 3000) { //while the difference between Date.now() and start is less than 3 seconds 
     console.log('blocked') 
    } 
} 

loop(); 

輸出將是:

// blocked 
// blocked 
// 
// ... would not return to the event loop while the loop is running 
// 
// blocked 
//...when the loop is over then the setInterval kicks in 
// resumed 
// resumed 

與發電機功能

let gen; 
let start = Date.now(); 

setInterval(() => console.log('resumed'), 500); 

function *loop() { 
    while ((Date.now() - start) < 3000) { //while the difference between Date.now() and start is less than 3 seconds 
     console.log(yield output()) 
    } 
} 

function output() { 
    setTimeout(() => gen.next('blocked'), 500) 
} 

gen = loop(); 
gen.next(); 

的輸出是:

// resumed 
// blocked 
//...returns control back to the event loop while though the loop is still running 
// resumed 
// blocked 
//...end of the loop 
// resumed 
// resumed 
// resumed 

使用JavaScript生成器可以幫助運行將產量回控制事件循環,同時它還是計算繁重的計算功能。

爲了更多地瞭解事件循環訪問 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/function*

https://davidwalsh.name/es6-generators

相關問題