javascriptnode.jseachasync.jswaterfall

Calling a callback function from async.each and processing the results


I'm just starting to work with Javascript and Node, and Async and callbacks concepts are not something I have under control right now.

I have to call a function for each element of a documents Array. This function will call to DB and get me an array of the document annotations. I want to get all the annotations and put them on the same array. Something similar to this:

     //function in an async waterfall
      function(docs,callback){
        let annotationsArray = [];
        async.each(docs, (doc, callback2) => {
          getAnnotationsFromDocument(doc.Id, callback2);
        }, function (err,annotations){
          if (err){
            callback(err);
          } 
          annotationsArray = annotationsArray.concat(annotations);
          callback(null, annotationsArray);
        });
        
      },
//Next waterfall function

About the getAnnotationsFromDocument function, this is a simplified structure of it:

function getAnnotationsFromDocument(docId,callback){
  
initDB();

  var async = require('async');
  async.waterfall([
    function authorize(callback){
      //checkAuthorization
(...)
    },
    function getRfpdocAnnotations(auth, metadata, callback){
      //call to DB
(...)
    },    
    function processRfpdocAnnotations(rfpDocAnnotations,metadata,callback){
 (...)
      callback(null,annotationsList);
    }
  ], function (err, result) {
    if(err) {
      callback(err);
    } else {
      callback(null, result);
    }       
  });   
}

Unfortunately, I'm unable to code it properly. I'm unable to get the results from the function before exiting the async.each. Could somebody explain me how to structurate the code for this?

Debugging I've found that the function getAnnotationsFromDocument gets the data and execute the last callback(null, result); properly, but when I get to function (err,annotations){, annotations is undefined.


Solution

  • Ok, I think I got it:

    To be quite honest, I'm not sure it's a correct answer, but it does what I was trying to achieve.

      // function part of an async.waterfall
      function(docs,callback){
        let annotationsArray = [];
        async.each(docs, (doc,callback2) => {    
          getAnnotationsFromDocument(doc._id, function(err,result){
              if (err){
                callback2(err);
              }else{
                annotationsArray = annotationsArray.concat(result);
              }
              callback2();
            })
        }, (err) =>{
          if( err ) {
            callback(err);
          } else {
            callback(null,annotationsArray); //to the next waterfall function
          }
        });