Node.js Asynchronous Function *Definition*

前端 未结 4 715
失恋的感觉
失恋的感觉 2020-12-30 15:16

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

相关标签:
4条回答
  • 2020-12-30 15:49

    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, i.e. first async_function_addthree, then the callback and then everything that follows the call to async_function_addthree, e.g. 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.

    0 讨论(0)
  • 2020-12-30 15:52

    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.

    0 讨论(0)
  • 2020-12-30 15:57

    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?

    0 讨论(0)
  • 2020-12-30 16:05

    Asynchronicity in NodeJS processes happens when you delegate some work to external processes (or probably some work in Node's C layer), that are e.g. 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.

    0 讨论(0)
提交回复
热议问题