2017-06-16 42 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对象。请原谅,如果我的术语有点不对 –