简体   繁体   中英

Node.js Asynchronous Function *Definition*

Please, just to clear something up in my head...

I am used to writing using asynchronous functions in libraries, but how do I write my own?

To illustrate my question I have made up a module called 'MadMathz'

I am aware that the following is an example usage of an asynchronous function :

//load module
var mM = require('./MadMathz');

//perform a function
mM.async_function_addthree(12, function(result) {
  console.log(result)
});

//do something straight afterwards
console.log('Logging this straight after instead of waiting for computation');

I'm aware that the second argument to the function is the callback, but how is a function such as 'async_function_addthree' defined? Let's say for the purpose of this example that async_function_addthree just adds 3 to the first argument.

I just confused myself so much trying to write what I thought it might be. Am I totally on the wrong track? I feel like I am close to getting there with node.js but this needs clearing up.

Please explain rather than linking me somewhere if possible. I'm sure others will benefit from this question.

Actually it sounds a little weird to create a " asynchronous " function without any further description or requirement. Usually, the usage is about avoiding long blocking periods. So if we have a function which triggers a database-query and we want to call another function when this is completed, that function should get called after the job is done and the original function instantely returns the control-flow back to Node (ECMAscript).

So if we have a construct like

function someJob( callback ) {
    // heavy work
    callback();
}

Now, this code still runs very synchronous . To bring that in an async state, we can invoke node's process.nextTick method

function someJob( callback ) {
    // heavy work
    process.nextTick( callback );
}

What happens now is, that Node will execute that callback method in a later run through its eventloop (and it does that somewhat intelligent too). Eventho nextTick claims to be much more efficient than setTimeout , its pretty much the same deal (from the ECMAscript coders perspective). So in a browser we could go like

function someJob( callback ) {
    // heavy work
    setTimeout( callback, 0 );
}

You would be correct if saying that the above example method doesn't make much sense at all, because the async state happens after the heavy work. Well, true. Infact, you would need to break down the heavy part into smaller peaces and make use of the same idea using .nextTick() to make this really efficient.

Thats also the reason for my confusion on the beginning, actually every task already offers callback possibilities for you.

This is not node.js module code, but I hope you get the idea.

Functions are first class objects in JavaScript. That's why you can assign them to variables and pass them to other functions like any value. Once you have a reference to a function, you simply call it by putting () after the function reference.

Example:

function async_function_addthree(a, callback) {
    callback(a + 3);
}

This adds 3 to the first argument and then calls the second argument passing the result to it. Keep in mind that you can name the parameters however you want to. All that matters is that the second parameter will hold a function which you can call.

But note: A function that accepts a callback is not automatically asynchronous. In this example, the code is still executed in the order it is defined, ie first async_function_addthree , then the callback and then everything that follows the call to async_function_addthree , eg the console.log .

You could add a setTimeout and call the callback delayed:

function async_function_addthree(a, callback) {
    setTimeout(function() {
        callback(a + 3);
    }, 1000);
}

This would call the callback after one second. Node.js even has a better way built-in, see jAndy's answer .

But even if your code is not asynchronous, using callback can be a wise design choice since it allows you to easily change the behaviour of the function and make it asynchronous later on without breaking existing code.

Asynchronicity in NodeJS processes happens when you delegate some work to external processes (or probably some work in Node's C layer), that are eg database queries, file system operations.

Usually there's no asynchronicity in plain JavaScript functions (Node.js is single threaded) there are not many valid cases for that. However, if it's really heavy, and you really want to do that, you may either delegate your work to other process (see child_process.fork) or split operations with help of setTimeout (to give process a breathe to handle other request), then indeed it should be configured as asynchronous function.

I came across this question while looking for the answer to it myself.

Basically, to write an asynchronous function in node, one of the arguments you give it should be a function; that function you'll call later on in your async function.

Then, when people are calling your function, they'll be able to define that function.

Here's an example of my code that I wrote in a synchronous way which didn't work, and how I rewrote it to be asynchronous and actually work.


The following code DOES NOT WORK:

//synchronous function that doesn't work
var google_request  = function(animal_name, sessionid){
    var options = {
        url: 'http://google.com',
        method: 'POST',
        json: {
            "animal": animal_name,
            "sessionid": sessionid
        }
    };

    request(options, function (error, response, body) {
        if (!error && response.statusCode == 200) {
            return body;
        }
    });
};

//use your function
var body = google_request("ant", "session1")
console.log(body); //this will return undefined

The following code DOES work:

//asynchronous function
var google_request  = function(animal_name, sessionid, callback_function){
    var options = {
        url: 'http://google.com',
        method: 'POST',
        json: {
            "animal": animal_name,
            "sessionid": sessionid
        }
    };

    request(options, function (error, response, body) {
        if (!error && response.statusCode == 200) {
            callback_function(body);
        }
    });
};

//use your function
google_request("ant", "session1", function(body){
    console.log(body); 
)};

This is maybe not the simplest example, but the changes I made to this function were very simple; I passed my function a third argument, called "callback_function", and instead of returning "body", I called my callback_function on body. Then below I used my function in the usual "Node" manner, instead of the synchronous manner.

You might also find this thread informative: How do I return the response from an asynchronous call?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM