【发布时间】:2017-06-16 16:09:31
【问题描述】:
我试图实现一个事件循环。循环的目的很简单:
- 如果队列不为空,则让任务成为队列中最早的条目。
- 处理任务
- 如果,任务生成返回值,缓存它。
- 检查队列中的任务。
- 如果队列不为空,则采用下一个任务作为当前任务上下文。
- 将缓存的返回值传递给新任务。
我在 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'
});
}
}
此实现与事件循环的区别如下:
- successCallback 可以实例化一个新任务作为其返回值,而不是维护一个任务数组,然后将其用作当前任务。
- 根据处理情况,任务状态必须改变(或者不改变,如果采用新的挂起任务,其状态为“未处理”)。
我认为问题在于 setImmediate 调用,它无法更改上下文状态,因为当前执行状态永远不会终止,并且会不断在事件队列中为同一任务添加新调用。
我希望我已经很好地解释了它,并感谢一些实施指南,以及我在理解事件队列时可能遇到的任何错误。
谢谢。
【问题讨论】:
-
我建议更好地缩进你的代码。我相信您是在
task.prototype.afterThat内部定义task.prototype._loop。 -
您的
while循环是一个无限循环。 JS 是单线程的,因此由于您的while循环,其他任何东西都无法运行。完成运行任务后,您需要检查ctx.state。setImmediate()没有阻塞。在你的while循环完成之前它不会运行,这是一个无限循环,所以它永远不会完成。
标签: javascript node.js concurrency eventqueue