Why is a function and a callback non-blocking in Node.JS?

The novice understanding of Node is that if I re-write synchronous, or in-line code, to utilize functions / callbacks, I can ensure that my code is non-blocking. I’m curious how this works in terms of the event stack. The simple example from here: Don’t understand the callback – Stackoverflow
is that this will block:

var post = db.query("select * from posts where id = 1");
doSomethingWithPost(post)
doSomethingElse();

While this wont:

callback = function(post){
doSomethingWithPost(post)
}

db.query("select * from posts where id = 1",callback);
doSomethingElse();

Ok, I understand that we should use callbacks. But in terms of the event stack why does this work? Javascript is single threaded.. in the first example line one makes use of an expensive and blocking I/O operation. Line 2 can’t execute till line one is done. Is this because line 2 requires information from line 1? Or is it because I/O events are just fundamentally blocking operations meaning that they seize control and don’t give it back until done…

In the second example the expensive I/O has been moved into a function, and we now have a callback function. Certainly the callback can’t execute until the I/O is done.. This would not change. So the difference in amount of time it takes to execute between one and two must primarily be what would happen if a second request hit the server.

If a second request hit example one, it wouldn’t be able to process until request 1 was done because of the blocking operation.. but in the example two.. does moving operations into functions automatically spawn child processes or act as multi-threaded? If Javscript is single threaded this would still pose a problem unless there was some way of doing parallel processing.. Does a function / callback only guarantee to be non-blocking IF we make use of non-blocking techniques like child processes, etc…

Problem courtesy of: Inc1982

Solution

Imagine you’re operating the cash register in a bakery. You handle your customers sequentially and synchronously, like this:

  1. Take order
  2. Tell baker to bake the bread
  3. Wait until bread is baked
  4. Charge money
  5. Deliver bread
  6. GOTO 1 — next customer

That will be very slow. Now, try instead to take the orders sequentially, but handle your customers asynchronously:

  1. Take order
  2. Tell baker to bake the bread, and notify you when finished. When notified:

    1. Charge money
    2. Deliver bread
  3. GOTO 1 — next customer

UPDATE:I refactored the above, so it more closely resembles a callback. You, the cashier, will hit step 3 immediately after giving the order to the baker. You will hit step 2.1 when the baker notifies you that the bread is ready.

In this manner, you will still deliver as much bread – you can only sell as much bread as your baker can bake. But you can deal with your customers in a more efficient manner, because instead of idly waiting for an order to come back, you start handling the next customer.

Now, you could go all sorts of fancy on this, and charge the money upfront, and tell the customer to pick up the bread at the other end of the desk, or something like that. I think Starbucks are pretty “evented” in this way. The cashier takes the order, issues a number of requests for stuff, and tells the customer to wait until everything is standing in the pickup area. Super-efficient.

Now, imagine that your friend starts operating another cash register. He follows your async example. You can handle more customers, even quicker! Note that the only thing you had to do was to put your friend there and give him your workflow.

You and your friend are two single-threaded event loops running in parallel. This is analog to two node.js
processes taking requests. You don’t have to to anything complex to parallelize this, you just run one more event loop.

So, no, “moving operations into functions” does not “automatically spawn child processes”. They are more akin to alarms — when this is finished, notify me and let me pick up at this point, “this point” being the code in your callback. But the callback will still be executed in the same process and the same thread.

Now, node.js
also operates an internal thread pool for IO. This is abstracted away from you: To continue the bakery analogy, let’s say you have a “baker pool” of bakers — to you, standing at the cash register, you don’t have to know about this. You just give them the order (“one sourdough loaf”) and deliver that order when you are notified that it’s finished. But the bakers are baking their bread in parallel, in their own “baker pool”.

Solution courtesy of: Linus Gustav Larsson Thiel

稿源:Node.js Recipes (源链) | 关于 | 阅读提示

本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 前端开发 » Why is a function and a callback non-blocking in Node.JS?

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录