Nodejs中的非阻塞事件循环

时间:2017-06-16 16:09:32

标签: javascript node.js concurrency eventqueue

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

  1. 如果队列不为空,则让任务成为队列中最早的条目。
  2. 处理任务
  3. 如果,task生成一个返回值,请将其缓存。
  4. 检查队列中的任务。
  5. 如果队列不为空,则采用下一个任务作为当前任务上下文。
  6. 将缓存的返回值传递给新任务。
  7. 我尝试以下列方式在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. 根据处理,任务状态必须更改(或者,如果采用新的挂起任务,则其状态为“未处理”)。
    3. 我认为问题是setImmediate调用,它无法更改上下文状态,因为当前执行状态永远不会终止并继续为事件队列中的同一任务添加新调用。

      我希望我已经很好地解释了它,并希望了解一些实施指南,以及我在理解事件队列时可能遇到的任何错误。

      感谢。

1 个答案:

答案 0 :(得分:2)

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

每次循环运行时,它会调用setImmediate()来调度要运行的任务,但该任务实际上无法运行,直到while循环结束。因此,您将陷入僵局,并且您将堆积大量要运行的任务(最终可能会溢出某些系统资源)。

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

setImmediate()没有阻止。您使用setImmediate()计划的功能在while循环完成之前不会运行,但while循环永远不会找到它的条件,因此它永远不会停止,因为在{{1循环完成。

相反,请调用下一个任务,完成后再检查while。由于您没有显示或描述如何使用或您真正想要实现的目标,因此我不确定建议的最佳实施方式。如果您需要更多帮助,那么您需要向我们展示更多关于您尝试完成的内容以及您希望如何使用此课程的内容。

我的猜测是你可以使用promises来完成你想要做的事情,而不必自己编写很多基础设施代码,因为promises是非常好的异步任务排序工具。

仅供参考,您的代码存在一些问题,例如缺少关闭括号和parens。您发布的内容甚至无法正确解析,更不用说运行了。并且,请在发布时正确缩进代码。