javascript - Nodejs 中的非阻塞事件循环

标签 javascript node.js concurrency eventqueue

我试图实现一个事件循环。循环的目的很简单:

  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 调用,它无法更改上下文状态,因为当前执行状态永远不会终止,并不断在事件队列中添加对同一任务的新调用。

我希望我已经很好地解释了它,并且希望得到一些实现指南以及我对事件队列的理解中可能出现的任何错误。

谢谢。

最佳答案

你的while循环是一个无限循环。 JS 是单线程的,因此在 while 循环完成之前没有其他东西可以运行。因为没有其他东西可以运行,所以 ctx.state 永远不会改变。由于 ctx.state 永远不会改变,因此您的 while 循环将永远运行。

每次循环运行时,它都会调用 setImmediate() 来安排任务运行,但该任务在 while 循环完成之前无法实际运行。因此,您陷入了僵局,并且将堆积大量要运行的任务(最终可能会溢出一些系统资源)。

您需要在完成任务运行后(可能在成功和失败回调中)检查 ctx.state,而不是在这样的循环中检查。

setImmediate() 不阻塞。您使用 setImmediate() 安排的函数在您的 while 循环完成之前不会运行,但是 while 循环永远不会找到其条件,因此它永远不会停止,因为在 while 循环完成之前没有其他东西可以运行。

相反,调用下一个任务,并在完成后检查 ctx.state。由于您没有展示或描述如何使用它或您真正想要完成什么,所以我不确定建议的最佳实现。如果您需要更多帮助,那么您需要向我们展示更多有关您想要完成的任务以及您希望如何使用此类的信息。

我的猜测是,您可以使用 Promise 来完成您想要做的事情,而无需自己编写大量基础设施代码,因为 Promise 是用于排序异步任务的非常好的工具。

<小时/>

仅供引用,您的代码有几个问题,例如缺少右大括号和括号。您发布的内容甚至无法正确解析,更不用说运行了。并且,发帖时请正确缩进代码。

<小时/>

关于javascript - Nodejs 中的非阻塞事件循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44593644/

相关文章:

java - 在 Scala 和第三方 Java 库中使用 Akka 的最佳实践

javascript - Node.js 未定义 :1 [SyntaxError: Unexpected end of input]

javascript - 我如何将全局变量传递给 Jade 模板

javascript - 将 Promise 与事件相结合

javascript - Vue-test-utils:在单个测试中多次使用 $nextTick

javascript - Sublime Text 2 Javascript 控制台

javascript - 两个异步函数调用填充同一个数组?

java - 在java中将本地对象传递给线程是不好的风格吗?

c - 为什么我的服务器实现不能同时正确运行?

javascript - 使用 CSS 或 Javascript 使多个背景图像可缩放?