0

I'm trying to run a named function that uses async.waterfall(), within another function that uses async.waterfall().

How should the callbacks be structured, so that the output of the inner function is passed to the outer function?

The following code doesn't use nested async's and works fine:

//nested_async_1.js

var async = require("async");

console.log("Script running");

// Inner function, to be called by the outer function
var InnerAsync = function(callback_inner_async) {

    async.waterfall([
        function (callback) {
            console.log("Inner function 1");
            callback(null, "results 1")
        },

        function (input_1, callback){
            console.log("function 2 " + input_1);
            callback(null, "results 2")
        }
    ],
    function (err, final_result) {
        if (err) {
            console.log("Server error: ", err);
            callback(err)
        }
        else{
            var return_val = "Final result " + final_result;
            console.log(return_val);
            callback_inner_async(return_val);
        }
    });
};


// Outer function
InnerAsync(function(result){
    console.log("Outer function " + result);
});

Output

C:\Data\>node nested_async_1.js  
Script running  
Inner function 1  
function 2 results 1  
Final result results 2  
Outer function Final result results 2  

While the following nested async code doesn't run:

//nested_async_2.js

var async = require("async");

console.log("Script running");

// Inner function, to be called by the outer function
var InnerAsync = function(callback_inner_async) {

    async.waterfall([
        function (callback) {
            console.log("Inner function 1");
            callback(null, "results 1")
        },

        function (input_1, callback){
            console.log("function 2 " + input_1);
            callback(null, "results 2")
        }
    ],
    function (err, final_result) {
        if (err) {
            console.log("Server error: ", err);
            callback(err)
        }
        else{
            var return_val = "Final result " + final_result;
            console.log(return_val);
            callback_inner_async(return_val);
        }
    });
};

// Outer function, which calls the inner function
async.waterfall([
    function(callback_outer){
        console.log("Outer function 1");
        callback_outer(null, "Outer result 1")
    },
    function(input_1, callback_outer){
        console.log("Outer function 2");
        // Run the inner function, and get the results
        // How should this be structured???
        callback_outer(null, InnerAsync())
    }
],
    function(err, final_outer_result){
        if(err){
            console.log("Error on outer function: " + err)
        }
        else {
            console.log("Final outer function");
            console.log(final_outer_result);
        }
    }
);

Output

C:\Data>node nested_async_2.js
Script running
Outer function 1
Outer function 2
Inner function 1
function 2 results 1
Final outer function
undefined
Final result results 2
C:\Data\nested_async_2.js:31
callback_inner_async(return_val);
^

TypeError: callback_inner_async is not a function
at C:\Data\nested_async_2.js:31:13
at C:\Data\node_modules\async\lib\async.js:52:16
at Immediate._onImmediate (C:\Data\node_modules\async\lib\async.js:1201:34)
at processImmediate [as _immediateCallback] (timers.js:374:17)

2 Answers 2

1

Instead of

function(input_1, callback_outer){
    console.log("Outer function 2");
    // Run the inner function, and get the results
    // How should this be structured???
    callback_outer(null, InnerAsync())
}

it should be

function(input_1, callback_outer){
    console.log("Outer function 2");
    InnerAsync(function(result) {
        console.log("Result from InnerAsync: ", result);
        callback_outer(null, result);
    });
}

to work as expected. In your nested_async_2.js, you call InnerAsync without a callback, so it fails when trying to call it.

Also there are couple of issues with error handling in InnerAsync. That function doesn't follow error-first callback pattern and as a related thing, the code will fail on these lines

function (err, final_result) {
    if (err) {
        console.log("Server error: ", err);
        callback(err) // will fail here
    }

(if an error occurs), because callback is not defined there.

Sign up to request clarification or add additional context in comments.

1 Comment

Works perfectly - Thanks @svlapin
0

I think you are calling the InnerAsync without any argument; so while calling the InnerAsync you are not passing the callback function callback_inner_async that by you are getting the error.

try this:

async.waterfall([
    function(callback_outer){
        console.log("Outer function 1");
        callback_outer(null, "Outer result 1")
    },
    function(input_1, callback_outer){
        console.log("Outer function 2");

        // Call InnerAsync with the callback function

        InnerAsync(callback_outer);
    }
],
    function(err, final_outer_result){
        if(err){
            console.log("Error on outer function: " + err)
        }
        else {
            console.log("Final outer function");
            console.log(final_outer_result);
        }
    }
);

1 Comment

Won't work, because InnerAsync calls its callback passing the result of successful execution as a first parameter, while async expects to get an error object. So it will be treated like a failed waterfall chain.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.