2017-06-16 47 views
-1

阻塞事件循環,我想實現一個事件循環。循環的目的很簡單:A暫無在的NodeJS

  1. 如果隊列不空,讓任務在隊列中的最老的項目。
  2. 進程任務
  3. 如果任務生成返回值,則將其緩存。
  4. 檢查隊列中的任務。
  5. 如果隊列不爲空,採取下一個任務作爲當前任務的上下文。
  6. 將緩存的返回值傳遞給新任務。

我嘗試一個實現中的NodeJS以下列方式:

function task(){ 
this.task = Array.prototype.shift.call(arguments); 
this.state = 'unprocessed'; 
this.successCallback = null; 
this.failureCallback = null; 
} 
task.prototype.afterThat = function(){ 
if(arguments.length > 1){ 
this.successCallback = Array.prototype.shift.call(arguments); 
this.failureCallback = Array.prototype.shift.call(arguments); 
} 
} 
task.prototype._loop = function(){ 
let ctx = this; 
while(ctx.state === 'unprocessed'){ // Source of problem 
    setImmediate(this.task, function(){ 
    // change ctx.state if needed 
    }, function(){ 
    // change ctx.state to 'processed' 
    }); 
} 
} 

這種實現方式,並且一個事件循環的之間的差別如下:

  1. 而不是保持一個數組的任務,successCallback可以實例化一個新任務作爲它的返回值,然後作爲當前任務被採用。
  2. 基於該處理中,任務狀態必須改變(或不,如果一個新的未決任務被通過了,具有其狀態爲「未處理的」)。

我相信問題是setImmediate調用,它不能更改上下文狀態,因爲當前執行狀態永遠不會終止,並且不斷爲事件隊列中的同一任務添加新的調用。

我希望我已經解釋清楚了,並希望得到一些實施指南,以及我對理解事件隊列的任何錯誤。

謝謝。

+1

我建議更好地縮進你的代碼。我相信你定義'task.prototype.afterThat'的'裏面task.prototype._loop'。 –

+1

你'while'循環是一個無限循環。 JS是單線程的,因此沒有別的東西可以運行,因爲你的while循環。完成運行任務後,您需要檢查'ctx.state'。 'setImmediate()'不是阻塞的。它不運行,直到你'while'循環完成這是一個無限循環,所以它從來沒有做過。 – jfriend00

回答

2

您的while循環是無限循環。 JS是單線程的,因此除非您的while循環完成,否則無法運行。因爲沒有別的可以運行,ctx.state永遠不會改變。由於ctx.state永遠不會更改,因此您的while循環將永遠運行。

每次循環運行時,它都調用setImmediate(),它調度要運行的任務,但該任務實際上不能運行,直到while循環結束。因此,你陷入了僵局,你將會堆積一大堆運行的任務(最終可能會溢出一些系統資源)。

完成運行任務(可能位於成功和失敗回調)後,您需要檢查ctx.state,而不是像這樣的循環。

setImmediate()沒有阻止。在while循環完成之前,您安排的功能setImmediate()不會運行,但while循環從未找到其條件,因此它永不停止,因爲在while循環完成之前沒有其他任何操作可以運行。

取而代之,調用下一個任務,完成後,檢查ctx.state。既然你沒有展示或描述如何使用它或你真的想要完成什麼,我不確定要建議的最佳實現。如果你想與更多的幫助,那麼你就需要向我們展示了很多關於你想要什麼來完成,如何你想使用這個類。

我的猜測是,你可以用承諾來完成你想要做什麼,而不必在自己寫的所有基礎設施得多的代碼,因爲承諾是測序異步任務非常好的工具。


僅供參考,代碼有幾個錯誤,例如缺少右花括號和parens。你發佈的內容甚至無法正確解析,更不用說運行了。並且,請在發佈時正確地縮進代碼。


+0

我會記下這一點。感謝您的建議。 –

+0

@AbrarHossain - 如果這回答了您的問題或者讓您回答了問題,那麼您可以通過點擊最能幫助您的答案旁邊的綠色複選標記來向社區表明這一點。這也將爲您遵循正確的程序在堆棧溢出方面贏得一些聲望點。 – jfriend00

+0

非常感謝您的努力。我還有一個問題。如果我想一個互斥添加到這個代碼,如檢查狀態,是否會幫助之前阻止CTX對象。請原諒,如果我的術語有點不對 –