-1

I'm trying to achieve the following:

Please consider running this in jasmine test framework that does not support async/await yet

async.waterfall calls a function that has async.each to trigger the creation of schemas and tables. The steps in async waterfall have to be executed sequentially i.e., schemas have to be created before creating tables. The problem I'm facing is that the first call to create schemas is executed but the callback is never returned to the async.waterfall. So, the next step in async.waterfall is never executed.

Timeline or Flow:
driverFunction (async.waterfall) invokes the createFunction.
The createFunction (asyncCreateSchema etc.,) function invokes the doSomething for each file in the array.
doSomething executes a jar file and returns a success or an error.

Here's my code:

'use strict'
let async = require('async');


function doSomething(file, done) {
  console.log(file);
  return done(null, true);
}

function asyncCreateSchema(files, done) {
  async.each(
    files,
    function(file, callback) {
      if (file.startsWith('schema')) {
        doSomething(file, callback);
      }
      else{
        callback();
      }
    },
    function(err) {
      if (err) {
        console.log(err);
      }
      console.log('create schema done');
    });
}

function asyncCreateTables(files, done) {
  async.each(
    files,
    function(file, callback) {
      if (file.startsWith('table')) {
        doSomething(file, callback);
      }
      else{
        callback();
      }
    },
    function(err) {
      if (err) {
        console.log(err);
      }
      console.log('create schema done');
    });
}

var files = ['schema.json', 'schema_1.json', 'table.json'];

async.waterfall([
    next => asyncCreateSchema(files, next),
    (nil, next) => asyncCreateTables(files, next),

  ],
  function(err, res) {
    if (err) {
      throw new Error("Setup error: " + err.message);
    } else {
      console.log(res);
    }
  }
);

What am I doing wrong here? Please explain the flow of callback functions in this scenario using the async npm package.

cosmicchichu
  • 63
  • 2
  • 8

1 Answers1

1

Why do you use that async.wattherfall function instead ES2017 async/await?

Please show me more code, some asynchronous code not only the console.log() to see how could I take off that ugly nodejs async library and replace with pure async/await syntax.

I just made you some code but I'm blind of what you want to to, please put the time-line of your code too, for example, this fn goes first, then the result is used in this other one.

async function doSomething(file) {
    var result = await new Promise((done, error) => {
        console.log(file)
        /* Here you execute async or sync operatios,
           when done, fire the done() if there is an error, you fire the error(error) */
        someTask(file, function(err, data){
            if (err)
                error(err)
            else
                done(data) //This data will be in result
        })
    })
    return result //data passed to done()
}

async function asyncCreateSchema(files, done) {
    for (var file of files) {
        if (file.startsWith('schema'))
            await doSomething(file);
    }
}

async function asyncCreateTables(files) {
    for (var file of files) {
        if (file.startsWith('table'))
            await doSomething(file);
    }
}


async function noNeedOfWaterfall () {
    var files = ['schema.json', 'schema_1.json', 'table.json']
    await asyncCreateSchema(files)
    await asyncCreateTables(files)
}

noNeedOfWaterfall()
    .then(() => console.log('all done'))
    .catch(e => {
        console.log('If you fire the error(err) in doSomething >>', e)
    })
Fernando Carvajal
  • 1,869
  • 20
  • 19
  • Thanks for the detailed explanation! The flow you have assumed is correct: a **driver** function calls create functions, for **each file** in a directory the create function calls the **doSomething** which ultimately executes a java jar. On the usage: The async package was already included in the project I'm working on. I believe the async package makes it easier to write readable code and also offers many ES2017 functions. Although you have given me a perfectly fine code, it would be great to understand how the callbacks are intended to work in the async package. – cosmicchichu Jan 26 '18 at 17:17
  • Don't you think the create function with the for loop and await is sequential? I am trying to implement parallelism: for instance, if there are ten schema files, the function should be able to fire these in parallel. – cosmicchichu Jan 26 '18 at 17:55
  • 2
    Sure if you want to achieve paralelism there is `Promise.all[array of data to process]` that allows you to get the result until all of them are finished. – Fernando Carvajal Jan 26 '18 at 20:10