10

I'm working on learning Node.js and all I hear in every tutorial is "Node is asynchronous and no -blocking!"

I've heard in regular browser JavaScript only certain things such as AJAX calls can be made asynchronous or non-blocking (using callbacks)... Is this true of Node.js as well, or are all Node.js callback functions made asynchronous/non-blocking?

Kris
  • 143
  • 2
  • 8
  • 1
    yes. this is the nature of javascript not node.js specific. – zs2020 Feb 19 '14 at 15:03
  • 6
    @zsong That isn't entirely accurate. – Brad Feb 19 '14 at 15:21
  • 1
    that is totally not accurate. read the spec. nothing about sync/async or blocking/non-blocking or io at all – vkurchatkin Feb 19 '14 at 15:24
  • 1
    It isn't the callback that's asynchronous. It's the function you're passing the callback to that's asynchronous, and therefore requires a callback. And not every function that takes a callback does so because it's going to do something async. – cookie monster Feb 19 '14 at 15:41

3 Answers3

17

are all Node.js callback functions made asynchronous/non-blocking?

No. Only I/O is usually asynchronous, but many other callbacks are synchronous. Always check the docs.

Examples of async functions:

  • Async Filesystem access (they have sync counterparts without callbacks, though)
  • Timers (setTimeout)
  • process.nextTick, setImmediate
  • most database connections
  • network connections
  • Promises

Examples of sync callbacks:

See also Are all javascript callbacks asynchronous? If not, how do I know which are? (including some other examples).

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    That isn't entirely accurate. You're right that I/O is multithreaded and the rest isnt, but many other callbacks are still asynchronous and called in a separate call stack. – Brad Feb 19 '14 at 15:22
  • What other callbacks do you mean? – vkurchatkin Feb 19 '14 at 15:23
  • When you pass a function as an argument, it doesn't mean it is a callback. For `forEach` is's iterator and for `EventEmitter` it's listener – vkurchatkin Feb 19 '14 at 15:30
  • 2
    @vkurchatkin: They're still [callbacks](https://en.wikipedia.org/wiki/Callback_(computer_programming)), aren't them? – Bergi Feb 19 '14 at 15:33
  • @Brad: Which other callbacks do you mean? – Bergi Feb 19 '14 at 15:34
  • @Bergi it looks like they are, generally speaking – vkurchatkin Feb 19 '14 at 15:37
  • @Bergi `zlib` and `crypto` has async capabilities, but they are not IO – vkurchatkin Feb 19 '14 at 15:38
  • 1
    @vkurchatkin: A function passed to another function for that other function to invoke is a callback. Doesn't matter if the callback will be invoked synchronously or asynchronously. The ECMAScript spec refers to the function passed to `.forEach()` for example as a "callback". – cookie monster Feb 19 '14 at 15:46
  • @vkurchatkin: zlib seems to do interprocess communication (via a stream), crypto seems to read from `/dev/random` - which I would both consider IO. Sure there are examples where code uses async capabilities for being non-blocking without doing IO, so I've generalized my statement by adding a "*usually*" :-) – Bergi Feb 19 '14 at 15:53
  • 1
    @Bergi I'm just talking about "other asynchronous callbacks" from Brad's comment, I agree about that part of your answer. To stop off-topic here is an interesting post by isaacs: http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony here talks more about consistency (always sync or always async), but still relevant – vkurchatkin Feb 19 '14 at 17:17
4

When you pass a callback to a function, you expect that function to call your callback function some other time. However, it isn't automatically asynchronous.

Suppose I have this code:

function callSomething(callback) {
  callback();
}

function theCallback() {
  // Do something time consuming here
}

callSomething(theCallback);

In this case, we're passing a callback, but the callback gets called immediately on the existing call stack. This is considered bad practice and is strongly discouraged in Node.js. If you want to call a callback fairly immediately, use process.nextTick():

function callSomething(callback) {
  process.nextTick(callback);
}

So the direct answer to your question is mostly yes. When you specify a callback to functions in Node.js, by convention they will be called on another callstack at a later point in time. But if you are using some bad code from someone who didn't know how to follow this convention, there is no guarantee.

Brad
  • 159,648
  • 54
  • 349
  • 530
  • True in general. Also worth mentioning that `setImmediate` could be used and I've heard couple of node core members saying that it's better to use it than `nextTick` to avoid `nextTick` specific problems (IO starvation mostly) – vkurchatkin Feb 19 '14 at 15:28
  • @vkurchatkin Interesting, I hadn't heard of setImmediate. I'm definitely swapping this out in some of my projects! http://stackoverflow.com/a/15349865/362536 – Brad Feb 19 '14 at 15:30
2

Nope, they are not automatically asynchronous. Consider this code:

function foo(array, filter, callback) {
    var result = []
    for (var i = 0; i < array.length; i++) {
        if (filter(array[i])) result.push(array[i]);
    }

    callback(result);
}

And now imagine a program like this:

foo([ 1, 2, 3, 4 ], function() { while(true); }, console.log);
console.log('Blocking?');

If foo would be asynchronous then Blocking? would immediatly appear, but it does not!


You can be pretty sure, however, that most / all of the standard library taking a callback is non-blocking async code. Most of it also has a Sync counterpart.

TimWolla
  • 31,849
  • 8
  • 63
  • 96