0

I am attempting to use promise to wait for async.mapLimit. I use it to run several shell scripts at the same time and I want to wait for all of them to finish executing before I continue past the log 'the end'. But I always get a undefined when using the return value for promise.

var myArray = [5,1,2,3,4];

const async = require('async');
const exec = require('child_process').exec;

function understandPromise() {

    const _waitForMe = async.mapLimit(myArray, 16, doSomeThing, function(err, results){
        console.log(results.length, 'should equal (doSomeThing)', myArray.length);
        console.log('err',err);

    });

    // This also gives undefined
    //const _waitForMe = async.mapLimit(myArray, 16, doSomeThing).then(a,b);
    _waitForMe.then(a,b);

    console.log('the end');

}

function doSomeThing(item, callback){

    let runCmd = './test.sh ' + item;
    console.log('before', runCmd);
    exec(runCmd, function (error, stdout, stderr) {
        console.log('error', error);
        console.log('stderr', stderr);
        console.log('stdout', stdout);
        console.log('after', runCmd);
        callback(null, item); // or actually do something to item
    });

}

understandPromise();

TypeError: Cannot read property 'then' of undefined relating to _waitForMe

Why doesn't mapLimit return a promise? I realize I am doing something fundamentally wrong here but i cannot figure out what. Other solutions not involving promise is also something I could consider.

Skipping the callback yields the same problem 'then' of undefined

const _waitForMe = async.mapLimit(myArray, 16, doSomeThing);

Similar SO questions like this only gives errors async.mapLimit with Promise

Update 1 after comments Commenters have suggested this:

async function understandPromise() {
        let results = await async.mapLimit(myArray, 8, doSomeThing);
        console.log('results', results.length);
        console.log('the end');
}

But this leads to (node:567) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'length' of undefined.

I still can't understand why the return of async.mapLimit is undefined when there is no callback involved.

Update 2

I got this to work from the comments but in the end it was that the async module was at an old version 1.5.2 and not at the newer 3.2.0

bits
  • 309
  • 2
  • 11
  • The version you put in comments, works [fine](https://repl.it/@trincottrincots/UsingAsyncMapLimit) (of course, none of the shell scripts will succeed in this demo, but that is not relevant). Check version of `async` package is the latest? – trincot Feb 27 '20 at 15:57
  • @trincot I tried your code, but it still runs past console.log('the end') before all of the shell script/your sleep has finished. ( async@3.2.0 ) – bits Feb 27 '20 at 23:55
  • Of course, you execute that synchronously. If you don't want that, then you must put that in function 'b'. – trincot Feb 28 '20 at 06:59

1 Answers1

0

The problem is you are passing the callback at the end of the function. The documentation clearly says it returns a promise, if no callback is passed. Remove function(err, results) and it should start returning a promise.

const results = await async.mapLimit(myArray, 16, doSomeThing);
console.log(results.length, 'should equal (doSomeThing)', myArray.length);
Ashish Modi
  • 7,529
  • 2
  • 20
  • 35
  • Do you mean like this? var _waitForMe = async.mapLimit(myArray, 16, doSomeThing); _waitForMe.then(a,b); This also becomes undefined – bits Feb 27 '20 at 15:40
  • @bits sorry what do you mean? I have added the code as well. – Ashish Modi Feb 27 '20 at 15:42
  • const results = await async.mapLimit(myArray, 16, doSomeThing); SyntaxError: await is only valid in async function, so this cannot work – bits Feb 27 '20 at 15:48
  • 1
    @bits, Of course you need to put that in an `async` function; that goes without saying. You can execute that async function immediately like an IIFE. – trincot Feb 27 '20 at 16:00
  • `async function understandPromise() {` – Ashish Modi Feb 27 '20 at 16:13