1

This question is regarding the sinlge threaded model of JavaScript. I understand that javascript is non-block in nature cause of its ability to add a callbacks to the async event queue. But if the callback function does infact take a long time to complete, won't JavaScript then be blocking everything else during that time as it is single threaded? How does nodejs handle such a problem? And is this an unavoidable problem for developers on the front end? I'm asking this question cause I have read that its generally good practice to keep function tasks as small as possible. Is it really because long tasks in javascript will actually block other tasks?

Lakmal Caldera
  • 1,001
  • 2
  • 12
  • 25
  • 1
    This is rather broad; what would your code be doing that's so time consuming? – Ja͢ck Nov 15 '14 at 02:43
  • 1
    "I understand that javascript is non-block in nature" - No, it is not. That's a design characteristic of some of node.js' API functions. JavaScript itself blocks during every function call. – Tomalak Nov 15 '14 at 02:53
  • Well its really more of question than problem I having right now. But I have noticed in the past if I was to do alot of dom manipulation in a single function, it does tend freeze the browser until it completes the task. That might be an example. – Lakmal Caldera Nov 15 '14 at 02:54
  • @Tomalak then how does nodejs handle long running tasks? And if javascipt is infact blocking, is that kind of a limitation in the language? – Lakmal Caldera Nov 15 '14 at 02:56
  • 1
    It does not *tend* to freeze the browser, it *does* freeze the browser. Every JavaScript function call does. Most of them happen too fast for you to notice, so it's not a problem until you do something time-intensive. – Tomalak Nov 15 '14 at 02:58
  • 2
    No, blocking is a limitation of *any* single-threaded environment. The answer is simple: Node is not single-threaded. – Tomalak Nov 15 '14 at 02:58
  • @Tomalak thnx man. That cleared it up for me :) – Lakmal Caldera Nov 15 '14 at 03:00
  • 1
    Also, node off-loads time-intensive tasks to the underlying operating system, which offers asynchronous functions for operations that involve waiting, like network and disk IO. – Tomalak Nov 15 '14 at 03:03
  • 1
    See the answer to http://stackoverflow.com/questions/5200821/grasping-the-node-js-alternative-to-multithreading (BTW there is something quite like that built into browsers: HTTP requests, i.e. Ajax, run on a different thread so they don't block the main thread. Same thing with Webworkers.) – Tomalak Nov 15 '14 at 03:04
  • 1
    Actually node does run as a single thread. The event loop is what makes asynchronous callbacks possible. – Jonathan Gray Nov 15 '14 at 03:14
  • See my answer here for more information: http://stackoverflow.com/a/19324665/362536 – Brad Nov 15 '14 at 03:54
  • 1
    @JonathanGray The JavaScript side of Node.js is single threaded, but native code can, and does, spin up a number of threads to do work. It is inaccurate to broadly say Node.js is single threaded, and is a large source of confusion. – Brad Nov 15 '14 at 03:54
  • Its hard to imagine how the browser is making its way on to bybrid mobile platforms and getting popular especially when javascript is blocking in nature. Which would mean you have to be very careful about the intensity of the work you do inside a single function, keeping it to a minimum. – Lakmal Caldera Nov 15 '14 at 04:06
  • @LakmalCaldera It's not as bad as you might think. What are you doing in JavaScript that ties things up for long periods of time, and has to run within that one call stack? – Brad Nov 15 '14 at 04:08
  • 1
    @Brad Node is in fact single threaded but obviously on multicore systems calls to external processes and native operating system APIs do indeed benefit from multithreaded processing. In order to take advantage of multithreaded environments from within Node you will need to run multiple concurrent instances of your application for example with the Cluster extension. – Jonathan Gray Nov 15 '14 at 04:10
  • 1
    @JonathanGray https://github.com/joyent/libuv/blob/master/src/threadpool.c – Brad Nov 15 '14 at 04:13
  • @Brad generally I avoid such situations. The fact is that it is there and because javascript is single threaded its hard to get around it if incase you happen to have a time consuming function. Its really theoritical for me. Practically I avoid it. – Lakmal Caldera Nov 15 '14 at 04:14
  • 1
    @Brad "A single instance of Node runs in a single thread. To take advantage of multi-core systems the user will sometimes want to launch a cluster of Node processes to handle the load." - http://nodejs.org/api/cluster.html – Jonathan Gray Nov 15 '14 at 04:15
  • 1
    @JonathanGray The documentation is oversimplified and technically inaccurate in that case, which is not surprising when you're looking at the cluster module docs. Obviously, there are times when you will want to run multiple processes. but that need isn't for every application. There are plenty of applications out there that utilize a single JavaScript thread and still consume a 16-core box, most of that load from a single Node.js process with the rest from the kernel. I don't know how else to prove that to you other than by the source code I linked to. – Brad Nov 15 '14 at 04:18
  • 1
    @JonathanGray See the explanations here... they explain it better than I have: http://stackoverflow.com/a/22644735/362536 – Brad Nov 15 '14 at 04:20
  • 1
    @Brad I'm not implying that a single node application can't utilize multicore systems efficiently. All single threaded applications benefit from multithreaded processing on capable systems. But there is no way to directly access mutiple threads using Node's interpreted JavaScript engine. That's what is meant when Node is referred to as "single-threaded". – Jonathan Gray Nov 15 '14 at 04:25
  • 1
    @JonathanGray Yes, agreed, completely. I feel it is important to be as accurate as possible and not make broad statements such as, "Node.js is single threaded." It is important that folks developing applications understand the basics of how it works, since it is so core to the architecture of Node.js. – Brad Nov 15 '14 at 04:27

2 Answers2

1

But if the callback function does infact take a long time to complete, won't JavaScript then be blocking everything else during that time as it is single threaded?

Yes.

How does nodejs handle such a problem?

Node.js handles nothing. How you handle concurrency is up to you and your application. Now, Node.js does have a few tools available to you. The first thing you have to understand is that Node.js is basically V8 (JavaScript engine) with a lightweight library split between JavaScript and native code bolted on. While your JavaScript code is single-threaded by nature, the native code can and does create threads to handle your work.

For example, when you ask Node.js to load a file from disk, your request is passed off to native code where a thread pool is used, and your data is loaded from disk. Once your request is made, your JavaScript code continues on. This is the meaning of "non-blocking" in the context of Node.js. Once that file on disk is loaded, the native code passes it off to the Node.js JavaScript library, which then executes your callback with the appropriate parameters. Your code continued to run while the background work was going on, but when your callback is dealing with that data, other JavaScript code is indeed blocked from running.

This architecture allows you to get much of the benefit of multithreaded code without having to actually write any multithreaded code, keeping your application straightforward.

I'm asking this question cause I have read that its generally good practice to keep function tasks as small as possible. Is it really because long tasks in javascript will actually block other tasks?

My philosophy is always to use what you need. It's true that if a request comes in to your application and you have a lot of JavaScript processing of data that is blocking, other requests will not be processed during this time. Remember though that if you are doing this sort of work, you are likely CPU bound anyway and doing double the work will cause both requests to take longer.

In practice, the majority of web applications are IO bound. They shuffle data from a database, reformat it, and send it out over the network. The part where they handle data is actually not all that time consuming when compared to the amount of time the application is simply waiting to hear back from the upstream data source. It is in these applications where Node.js really shines.

Finally, remember that you can always spawn child processes to better distribute the load. If your application is that rare application where you do 99% of your work load in CPU-bound JavaScript and you have a box with many CPUs and/or cores, split the load across several processes.

Brad
  • 159,648
  • 54
  • 349
  • 530
0

Your question is a very large one, so I am just going to focus on one part.

if the callback function does infact take a long time to complete, won't JavaScript then be blocking everything else during that time as it is single threaded? (...) Is it really because long tasks in javascript will actually block other tasks?

Non-blocking is a beautiful thing XD

The best practices include:

  • Braking every function down into its minimum functional form.
  • Keep CallBacks asynchronies, THIS is an excellent post on the use of CallBacks
  • Avoid stacking operations, (Like nested Loops)
  • Use setTimeout() to brake up potentially blocking code
  • And many other things, Node.JS is the gold standard of none blocking so its worth a look.

--

--

setTimeout() is one of the most important functions in no-blocking code

So lets say you make a clock function that looks like this:

function setTime() {
    var date=new Date();
    time = date.getTime()
    document.getElementById('id').innerHTML = time;

}
while(true){setTime();}

Its quite problematic, because this code will happily loop its self until the end of time. No other function will ever be called. You want to brake up the operation so other things can run.

function startTime() {
    var date=new Date();
    time = date.getTime()
    document.getElementById('id').innerHTML = time;
    setTimeout(startTime(),1000);
}

'setTimeout();' brakes up the loop and executes it every 1-ish seconds. An infinite loop is a bit of an extreme example. The point is 'setTimeout();' is great at braking up large operation chains into smaller ones, making everything more manageable.

Community
  • 1
  • 1
Burdock
  • 1,085
  • 1
  • 9
  • 22