Using async module to fire a callback once all fil

2020-07-17 07:57发布

问题:

I'm using caolan's 'async' module to open an array of filenames (in this case, template file names).

Per the documentation, I'm using async.forEach(),so I can fire a callback once all operations have completed.

A simple test case is:

var async = require('async')
var fs = require('fs')

file_names = ['one','two','three'] // all these files actually exist

async.forEach(file_names, 
    function(file_name) {
        console.log(file_name)
        fs.readFile(file_name, function(error, data) {
            if ( error) {   
                console.log('oh no file missing')   
                return error
            } else {
                console.log('woo '+file_name+' found')
            }       
        })
    }, function(error) {
        if ( error) {   
            console.log('oh no errors!')
        } else {
            console.log('YAAAAAAY')
        }
    }
)

The output is as follows:

one
two
three
woo one found
woo two found
woo three found

I.e, it seems the final callback isn't firing. What do I need to do to make the final callback fire?

回答1:

The function that is being run across all items must take a callback, and pass its results to the callback. See below (I've also separated fileName to improve readability):

var async = require('async')
var fs = require('fs')

var fileNames= ['one','two','three']


// This callback was missing in the question.
var readAFile = function(fileName, callback) {
    console.log(fileName)
    fs.readFile(fileName, function(error, data) {
        if ( error) {   
            console.log('oh no file missing')   
            return callback(error)
        } else {
            console.log('woo '+fileName+' found')
            return callback()
        }       
    })
}

async.forEach(fileNames, readAFile, function(error) {
    if ( error) {   
        console.log('oh no errors!')
    } else {
        console.log('YAAAAAAY')
    }
})

Returns:

one
two
three
woo one found
woo two found
woo three found
YAAAAAAY


回答2:

This is the best way to do it in my opinion. The results param will have an array of strings containing the file data and all of the files will be read in parallel.

var async = require('async')
    fs    = require('fs');

async.map(['one','two','three'], function(fname,cb) {
  fs.readFile(fname, {encoding:'utf8'}, cb);
}, function(err,results) {
  console.log(err ? err : results);
});