1

I have an array with some IDs like a = [abc,cde,efg]. I pass this array and a second one containing the names with fit to the IDs to a child process in Node. I want to wait until the child process finished and processes the next array member after that.

The code to achieve it is (with the suggested Edit):

function downloadSentinel(promObj) {
return new Promise((resolve,reject) => {
    function makeRequest(url, i, callback) {
        url = promObj.ID;
        name = promObj.Name;
        var sys = require('util'),
            exec = require('child_process').exec,
            child;

        var directory = __dirname.substring(0, __dirname.indexOf("\\app_api"));
        console.log(directory);



        child = exec(directory + '\\downloadProducts.sh' + promObj.ID[i] + ' ' + promObj.Name[i], function (error, stdout, stderr) {
            child.on("error", function (error) {
                console.log(error);
            })

            child.stdout.on('data', function (data) {
                console.log(data.toString());
            });

            child.on('exit', function(exit) {
            console.log(exit);    
            callback();


            })


        })



    }

    async.eachOfLimit(promObj.requestURLS, 2, makeRequest, function (err) {
        if (err) reject(promObj)
        else {
            resolve(promObj);
        }
    });
});
}

I am using npm-async to control the concurrency flow because I want to limit the curl requests I do inside the shell script. The shell sript works without an error. Now the script is only called twice because of the async.eachOfLimit limit. Then the other array IDs are not processed anymore.

EDIT

This is the code I tried at last, but then all possible urls are evoked instead of only 2. I found this here Another Stackoverflow question. I also tried with async.timesLimit

function downloadSentinel(promObj,req,res) {
     async.eachOfLimit(promObj.requestURLS, 2,function (value,i,callback) {
         console.log('I am here ' + i + 'times');
         url = promObj.requestURLS;
         name = promObj.Name;
         console.log(promObj.requestURLS);
         var sys = require('util'),
             exec = require('child_process').exec,
             child;

         var directory = __dirname.substring(0, __dirname.indexOf("\\app_api"));
         console.log(directory);

         console.log("executing:", directory + '\\downloadProducts.sh ' + promObj.requestURLS[i] + ' ' + promObj.Name[i]);
         child = exec(directory + '\\downloadProducts.sh' + ' ' + promObj.requestURLS[i] + ' ' + promObj.Name[i], function (error, stdout, stderr) {

             if (error != null){
                 console.log(error);
             }



            // this task is resolved
            return  callback(error, stdout);
         });

     }, function (err) {
        if (err) console.log('error')
        else {
            console.log('Done');
        }
    });

     }

What have I missed? Thanks in advance.

dwalin93
  • 83
  • 10

1 Answers1

1

exec is asynchronous, it does not wait for the launched process to finish.

Move the call to callback() inside the child.on('exit' ...) handler or use execSync

attdona
  • 17,196
  • 7
  • 49
  • 60
  • Thanks for that. Now I have the probem, that only two items of the array are downloaded and then nothing happens anymore. Does the callback end the whole ` async.eachOfLimit()` function? – dwalin93 Feb 17 '18 at 17:30
  • No, you set the limit parameter of eachOfLimit to 2 (2nd arg) and this limit the numbers of async operations. – attdona Feb 17 '18 at 17:45
  • I understood this function as follows: Lets say there are 5 items in the array. The function `makeRequest` is called 2 times so the first two items from the array are downloaded. After the callback, the next two items are downloaded and so on. Am I thinking right? – dwalin93 Feb 17 '18 at 17:57
  • Yes, you are thinking right, I misunderstood the meaning of limit. Rereading the docs it is clear that eachOfLimit callback is invoked when all items are iterated or an error occur (and this should stop the iteration), so probably this is your case. – attdona Feb 17 '18 at 18:12
  • I figured out that depending on which limit I set the number of times the child process is called. After the callback the function ends and is not called again. Any ideas? – dwalin93 Feb 17 '18 at 19:34
  • see [this](https://gist.github.com/attdona/dc5018d9586e8c73d1d15c1040c9cc44), I've tried to keep the example as similar as possible to your code. I hope it could help to go. – attdona Feb 17 '18 at 21:10
  • Thanks for your help, I logged inside the `makeRequest` function and it is still called only once. Maybe I should try something else than `async.eachOfLimit` ... I think it is simply an issue between child processes and the async library. – dwalin93 Feb 18 '18 at 13:50