admin管理员组

文章数量:1357399

I'm going through the "Functional Javascript Workshop" through Nodeschool. One of the exercises is titled "Blocking Event Loop" and I am having difficulty understanding it. With past exercises, I have made sure to really try to understand the solution so that if I were to have to redo the problem, I would understand how to solve it (as opposed to hacking away at it the first time). But this concept is really challenging me.

Modify the recursive repeat function provided in the boilerplate, such that it does not block the event loop (i.e. Timers and IO handlers can fire). This necessarily requires repeat to be asynchronous.

A timeout is queued to fire after 100 milliseconds, which will print the results of the test and exit the process. repeat should release control of the event loop to allow the timeout to interrupt before all the operations plete.

Try to perform as many operations as you can before the timeout fires!

Boilerplate

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

module.exports = repeat

Solution

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

I have sought to understand setTimeout better and I somewhat understand how it works. But I do not understand some of the language and concepts in the question itself:

Modify the recursive repeat function provided in the boilerplate, such that it does not block the event loop (i.e. Timers and IO handlers can fire). This necessarily requires repeat to be asynchronous.

I don't understand how the solution, which makes every 10th repeat async, prevents repeat from blocking the event loop. I'm assuming the event loop and event queue are like the same things? For instance clicks get placed on the event queue while the javascript code is running synchronously through its code until the execution stack is empty and then the queue gets looked at. How does making every 10th repeat async prevent the queue from being blocked -- my understanding of "being blocked" is that items in the queue are blocked until the stack is empty, at which point javascript looks at what is in the queue. So lets say at repeat 10, 20, 30 etc, this code makes those repeats async, but doesn't it still continue through all the nums until it hits zero, at which point the stack is now empty, before javascript looks at the queue? So how does this solution resolve that blocking like the question asks?

Next, the question refers to "releasing control". No clue what that means. What is control and how is it released and what is it released to?

Immediately after that the question says "allow the timeout to interrupt before all the operations plete." Does interruption mean that basically every 10th repeat is interrupted (not allowed to plete until the synchronous code ends)?

Finally, the challenge at the end to try and perform as many operations as one can before the timeout fires... I also don't see how that applies to the solution. The setTimeout doesn't even seem to have a set duration.

I'm going through the "Functional Javascript Workshop" through Nodeschool. One of the exercises is titled "Blocking Event Loop" and I am having difficulty understanding it. With past exercises, I have made sure to really try to understand the solution so that if I were to have to redo the problem, I would understand how to solve it (as opposed to hacking away at it the first time). But this concept is really challenging me.

Modify the recursive repeat function provided in the boilerplate, such that it does not block the event loop (i.e. Timers and IO handlers can fire). This necessarily requires repeat to be asynchronous.

A timeout is queued to fire after 100 milliseconds, which will print the results of the test and exit the process. repeat should release control of the event loop to allow the timeout to interrupt before all the operations plete.

Try to perform as many operations as you can before the timeout fires!

Boilerplate

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

module.exports = repeat

Solution

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

I have sought to understand setTimeout better and I somewhat understand how it works. But I do not understand some of the language and concepts in the question itself:

Modify the recursive repeat function provided in the boilerplate, such that it does not block the event loop (i.e. Timers and IO handlers can fire). This necessarily requires repeat to be asynchronous.

I don't understand how the solution, which makes every 10th repeat async, prevents repeat from blocking the event loop. I'm assuming the event loop and event queue are like the same things? For instance clicks get placed on the event queue while the javascript code is running synchronously through its code until the execution stack is empty and then the queue gets looked at. How does making every 10th repeat async prevent the queue from being blocked -- my understanding of "being blocked" is that items in the queue are blocked until the stack is empty, at which point javascript looks at what is in the queue. So lets say at repeat 10, 20, 30 etc, this code makes those repeats async, but doesn't it still continue through all the nums until it hits zero, at which point the stack is now empty, before javascript looks at the queue? So how does this solution resolve that blocking like the question asks?

Next, the question refers to "releasing control". No clue what that means. What is control and how is it released and what is it released to?

Immediately after that the question says "allow the timeout to interrupt before all the operations plete." Does interruption mean that basically every 10th repeat is interrupted (not allowed to plete until the synchronous code ends)?

Finally, the challenge at the end to try and perform as many operations as one can before the timeout fires... I also don't see how that applies to the solution. The setTimeout doesn't even seem to have a set duration.

Share Improve this question asked Nov 17, 2015 at 23:00 user4853user4853 3633 silver badges8 bronze badges 3
  • you seem to be stuck on this every 10th repeat which makes me think you may be approaching this from the wrong perspective – Jaromanda X Commented Nov 17, 2015 at 23:11
  • @JaromandaX My intent of referencing the every 10th repeat is mostly to mark where in the solution the setTimeout function will run. From reading some other posts on this particular question, the choice of 10 is not important -- it could be any number. Anyway, I would appreciate being directed to a correct perspective. My goal is to really understand the concept behind this question so that I'd be capable of answering it on my own. – user4853 Commented Nov 17, 2015 at 23:28
  • My point is that I believe you are approaching the solution the wrong way. I'm possibly (probably) wrong. I made the observation to perhaps make you step back and re-assess the problem, however, looking at the question again, I see that the solution is not your solution, and you are having trouble understanding it. – Jaromanda X Commented Nov 17, 2015 at 23:34
Add a ment  | 

1 Answer 1

Reset to default 10

The message queue (you refer to it as the event queue) is a list of messages to be processed

The event loop processes these messages one by one to pletion

The blocking version of the repeat function you posted would be

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

    operation()

    repeat(operation, --num)
}

You can see that this recursively calls itself until num <= 0, so this wont plete until num <= 0, therefore no new messages will be processed by the event loop until this finishes

Contrast this with the non blocking version

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)
    }
}

every 10 iterations, rather than recursively calling repeat, this function places (by virtue of the setTimeout) the next call to repeat to the end of the message queue and does nothing else (therefore is pleted)

this allows the event loop to process any and all messages that were placed on the message queue during the 10 iterations of repeat before the setTimeout call, and only once those messages have been processed to pletion will the callback in setTimeout be executed, which will be the next iteration of the repeat function

本文标签: javascriptBlocking Event LoopStack Overflow