How do you write non-blocking modules?

Coming from an entirely different background, the way Node.js works is still a very foreign concept to me. I'm grasping the concept of using callbacks in your functions, but it's hard for me to actually put this into practice when I'm trying to support modular development and as a result better scaling.

For example, how would I return the results of a function back to my code, or rather, access without blocking? I've been reading up on it, but I just can't wrap my head around how this is accomplished, as everybody is giving me a different answer. Take a log function, for example:

exports.log = function (req, res, type) {
    // do stuff here
}

Thanks in advance.

function doStuff (someValue, someOtherValue, someCallBack) {
    console.log("First Value: " + someValue);

    while(someValue-- != 0) {console.log(someValue);}
    someCallBack(someOtherValue);
}

function delayEventLoopMore(someValue) {

    while(someValue-- != 0) {console.log('The value:' + someValue);}
}

doStuff(100000, 100000, delayEventLoopMore);

console.log('YAY!');

The previous code is an example of blocking code involving callbacks. Clearly simply providing the callback parameter has not made this code non-blocking. If you run it you should clearly see two different counts down from 100,000 to 0, and then finally printing 'YAY'. If this function were non blocking, we would certainly have had plenty of time to print 'Yay'. If you doubt this feel free to increase the values to millions or even billions. 'Yay' will always be the last thing printed.

True async, non-blocking behavior comes from the V8 backend. The only way to replicate this is to produce a native extension.

Here are two versions of this function:

exports.log = function (someFileName) {
    var results;

    results = fs.readFileSync(someFileName);

    return results;
}


exports.log = function (someFileName, callback) {
    var results;


    fs.readFile(someFileName, function(data) {
        results = data;//unnecessary just for clarity!
        callback(results);
    }
}

The first version assumes that whatever operations you are doing are synhcronous. There is absolutely no benefit to using a callback in this situation. Just return the results. It will result in the exact same amount of delay in the event loop either way. If the work that you have to do here is very CPU intensive, you're probably stuck with this.

If it is I/O intensive, you can do one of two things. A: take advantage of node modules already developed that are Async: http, fs, there's some good mongodb stuff, etc... or if nothing exists for your use case, develop a native extension for it. Regardless, the way you then return the results, is by taking a callback the user supplied you, and calling this callback with the contents of 'results' you have built up over the course of your asynchronous operations.