hussain
hussain

Reputation: 7123

How to call function once forEach loop is done?

I have to sort some data based on condition and push it to new array sortedFiles , so basically once forEach loop is done i want to call asyncFiles() function and pass the object to it, but its not happening with below code. Any idea what is implemented wrong or any better approach to achieve this task ?

filesData is object that contains files from directory.

ctrl.js

if (searchObj.searchEnv === 'stat') {
  stDirectory.readDirectory(function(files) {
    filesData.logFiles.forEach(function(file) {
      var sortedFiles = [];
      var fileDate = new Date(file.fileDate).getTime();
      searchStartDate = new Date(searchStartDate).getTime();
      searchEndDate = new Date(searchEndDate).getTime();
      if (fileDate - searchStartDate > 0 && searchEndDate - fileDate > 0) {
        console.log('File Date', file);
        sortedFiles.push(file);
      }
    }, function() {

      console.log(filesData.logFiles);
      filesData.logFiles = sortedFiles;
      asyncFiles(filesData); // Not being called.
    });
  });
}

Upvotes: 2

Views: 2371

Answers (3)

zlwaterfield
zlwaterfield

Reputation: 841

From your code example asyncFiles is not called because forEach takes 1 arg not 2 but if you want to call a function after a forEach loop that is doing async calls then you can use the map function in async library.

https://caolan.github.io/async/docs.html#map

async.map(filesData.logFiles, (logFile, next) => {
   // Do some work with logFile
   next();
}, (err, results) => {
   // Call function after mapping is complete
});

Upvotes: 0

Abhinav Galodha
Abhinav Galodha

Reputation: 9928

forEach doesn't take 2 functions as Parameters.

From MDN below is the Syntax for the forEach Function.

arr.forEach(function callback(currentValue, index, array) {
    //your iterator
}[, thisArg]);

So, the second function is being ignored and doesn't make sense. Since, you are not doing any async operation in forEach. Therefore you can rely that once the forEach is complete the required work is done and it is safe to call the function asyncFiles after completing the forEach Function.

if (searchObj.searchEnv === 'stat') {
        stDirectory.readDirectory(function(files){
        filesData.logFiles.forEach(function(file){
            var sortedFiles = [];
            var fileDate = new Date( file.fileDate ).getTime();
            searchStartDate = new Date( searchStartDate ).getTime();
            searchEndDate = new Date( searchEndDate ).getTime();
                 if (fileDate - searchStartDate > 0 && searchEndDate - fileDate > 0) {
                        console.log('File Date',file);
                        sortedFiles.push(file);
                  }
              });


              console.log(filesData.logFiles);
              filesData.logFiles = sortedFiles;
              asyncFiles(filesData); // Not being called.


        });
    }

Upvotes: 1

Bergi
Bergi

Reputation: 665545

forEach is not an asynchronous function that takes an optional completion callback. Just do the stuff after your invocation:

if (searchObj.searchEnv === 'stat') {
    stDirectory.readDirectory(function(files){
        var sortedFiles = []; // move this in front of the loop
        filesData.logFiles.forEach(function(file){
            var fileDate = new Date( file.fileDate ).getTime();
            var searchStartDate = new Date( searchStartDate ).getTime(); // add missing
            var searchEndDate = new Date( searchEndDate ).getTime(); //     `var`s
            if (fileDate - searchStartDate > 0 && searchEndDate - fileDate > 0) {
                console.log('File Date',file);
                sortedFiles.push(file);
            }
        });
        console.log(filesData.logFiles);
        filesData.logFiles = sortedFiles;
        asyncFiles(filesData); // Now being called.
    });
}

Upvotes: 4

Related Questions