2

I am confused about how to use async.waterfall method to clean up my callbacks. I have a couple functions that are making API calls and returning back results from those API calls via callbacks. I want to pass the results from one api call to the next. I'd also ideally like to enclose these calls in separate functions rather than paste them directly into the async.waterfall control flow (for readability).

I can't quite figure out if you can call a function that has a callback in it, and it will wait for the callback before going to the next function, or not. Also, when the API SDK requires a callback, do I name it to match the callback name in the async.waterfall (in this case called 'callback')?

I may be mixing a lot of things together. Hopefully someone can help me unravel this. Below is a partial code snippet of what I'm trying to do...

async.waterfall([ function(callback){ executeApiCallOne(); callback(null, res); }, function(resFromCallOne, callback){ executeApiCallTwo(resFromCallOne.id); callback(null, res); }], function (err, res) { if(err) { console.log('There was an error: ' + err); } else { console.log('All calls finished successfully: ' + res); } } ); //API call one var executeApiCallOne = function () { var params = { "param1" : "some_data", "param2": "some_data" }; var apiClient = require('fakeApiLib'); return apiClient.Job.create(params, callback); // normally I'd have some callback code in here // and on success in that callback, it would // call executeApiCallTwo // but it's getting messy chaining these }; //API call two var executeApiCallTwo = function (id) { var params = { "param1" : "some_data", "param2": "some_data", "id": id }; var apiClient = require('fakeApiLib'); // do I name the callback 'callback' to match // in the async.waterfall function? // or, how do I execute the callback on this call? return apiClient.Job.list(params, callback); }; 

1 Answer 1

3

If one of your api calls returns successfully, you call the local callback with null as the first argument. Otherwise, call it with an error, and async.waterfall is going to stop the execution and run the final callback. For example (didn't test id):

async.waterfall([ function(callback){ executeApiCallOne(callback); }, function(resFromCallOne, callback){ executeApiCallTwo(resFromCallOne.id, callback); }], function (err, res) { if(err) { console.log('There was an error: ' + err); } else { // res should be "result of second call" console.log('All calls finished successfully: ' + res); } } ); //API call one var executeApiCallOne = function (done) { var params = { "param1" : "some_data", "param2": "some_data" }; var apiClient = require('fakeApiLib'); return apiClient.Job.create(params, function () { // if ok call done(null, "result of first call"); // otherwise call done("some error") }); }; //API call two var executeApiCallTwo = function (id, done) { var params = { "param1" : "some_data", "param2": "some_data", "id": id }; var apiClient = require('fakeApiLib'); // do I name the callback 'callback' to match // in the async.waterfall function? // or, how do I execute the callback on this call? return apiClient.Job.list(params, function () { // if ok call done(null, "result of second call"); // otherwise call done("some error") }); }; 
Sign up to request clarification or add additional context in comments.

1 Comment

Awesome, thanks! This is working for me with a couple small changes. For anyone else who is confused, the key I learned here is that you don't have to make the callback inside the waterfall function, you can offload it to your step function (ie. executeApiCallOne()) and call it according to the comments in this answer. Only change I made is there is no need for return statement in the executeApiCallOne() and executeApiCallTwo() functions. Thanks!!!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.