阻止事件循环

时间:2015-11-17 23:00:04

标签: javascript asynchronous functional-programming

我正在通过"功能性Javascript研讨会"通过Nodeschool。其中一个练习名为“阻止事件循环”#34;我很难理解它。通过以前的练习,我确保真正尝试理解解决方案,这样如果我不得不重做问题,我会理解如何解决它(而不是第一次破解它)。但这个概念真的让我很难受。

  

修改样板中提供的递归重复函数,例如   它不会阻止事件循环(即计时器和IO处理程序可以   火)。这必然要求重复是异步的。

     

超时在100毫秒后排队等待,这将打印出来   测试结果并退出过程。重复应该释放   控制事件循环以允许超时在所有操作完成之前中断。

     

尝试在超时发生之前执行尽可能多的操作!

     

样板

function repeat(operation, num) {
  // modify this so it can be interrupted
  if (num <= 0) return
  operation()
  return repeat(operation, --num)
}

module.exports = repeat
  

解决方案

function repeat(operation, num) {
        if (num <= 0) return

        operation()

        // release control every 10 or so
        // iterations.
        // 10 is arbitrary.
        if (num % 10 === 0) {
          setTimeout(function() {
            repeat(operation, --num)
          })
        } else {
          repeat(operation, --num)
        }
      }

module.exports = repeat

我试图更好地理解setTimeout,我有点理解它是如何工作的。但我不明白问题本身的一些语言和概念:

  

修改样板中提供的递归重复函数,   这样它不会阻止事件循环(即计时器和IO处理程序可以触发)。这必然需要重复   异步。

我不明白使每10次重复异步的解决方案如何阻止重复阻止事件循环。我假设事件循环和事件队列是一样的东西?例如,点击进入事件队列,而javascript代码通过其代码同步运行,直到执行堆栈为空,然后查看队列。如何使每10次重复异步防止队列被阻止 - 我理解&#34;被阻止&#34;是队列中的项被阻塞,直到堆栈为空,此时javascript查看队列中的内容。所以,让我们说重复10,20,30等,这段代码使得那些重复异步,但它还没有继续通过所有的nums直到它达到零,此时堆栈现在是空的,在javascript看之前队列?那么这个解决方案如何解决阻塞问题呢?

接下来,问题涉及&#34;释放控制&#34;。不知道这意味着什么。什么是控制,它是如何发布的以及它发布的内容是什么?

在此之后,问题显示&#34;允许超时在所有操作完成之前中断。&#34;中断是否意味着基本上每10次重复都被中断(在同步代码结束之前不允许完成)?

最后,在超时之前尝试执行尽可能多的操作的最后挑战......我也不知道这对解决方案有何影响。 setTimeout似乎没有设定的持续时间。

1 个答案:

答案 0 :(得分:6)

消息队列(您将其称为事件队列)是要处理的messages的列表

事件循环将这些消息逐个处理完成

您发布的重复功能的阻止版本将是

function repeat(operation, num) {
    if (num <= 0) return

    operation()

    repeat(operation, --num)
}

你可以看到这个递归调用自己直到num&lt; = 0,所以这不会完成,直到num&lt; = 0,因此事件循环不会处理新的消息,直到完成

将此与非阻止版本

进行对比
function repeat(operation, num) {
    if (num <= 0) return

    operation()

    // release control every 10 or so
    // iterations.
    // 10 is arbitrary.
    if (num % 10 === 0) {
        setTimeout(function() {
            repeat(operation, --num)
        })
    } else {
        repeat(operation, --num)
    }
}

每10次迭代,而不是递归调用repeat,此函数将(通过setTimeout)下一次调用重复到消息队列的 end ,并且不执行任何其他操作(因此完成) )

这允许事件循环处理在setTimeout调用之前的10次迭代重复期间放置在消息队列中的任何和所有消息,并且只有当这些消息处理完成后才会执行setTimeout中的回调,这将是重复函数的下一次迭代