Search code examples
javascriptnode.jsasync-awaitnode-async

node async library filterLimit always returns undefined


I'm trying to async filter a list of file paths to return only existing files. I'm using the async library's filterLimit along with fs-extra. Function below:

const asyncFilter = require('async').filterLimit;
const fsExtra = require('fs-extra');

async function filterFiles(fileList){
  const existing = await asyncFilter(fileList, 5, (file, callback) => {
    console.log(file); // looks good

    fsExtra.pathExists(file, (err, exists) => {
       const result = err ? false : exists;
       console.log(result); // looks good (boolean)

       callback(null, result);
    });
  });

  console.log(existing); // always undefined...
}

Solution

  • EDIT 2: Both suggestions below do not work... here is a working version where the deprecated fs.exists() was replaced with fs.access()

    const async = require('async');
    const fs = require('fs');
    
    async function filterFiles(fileList) {
        try {
    
            const result = await async.filterLimit(fileList, 5, function(filePath, callback) {
                fs.access(filePath, function(err) {
                    callback(null, !err)
                });
            });
    
            console.log(result);
        } catch(err) {
            console.log(err);
        }
    };
    

    Can't you simply do:

    NOT WORKING

        const asyncFilter = require('async').filterLimit;
        const fs = require('fs');
    
        async function filterFiles(fileList) {
            let result = [];
            await asyncFilter(fileList, 5, fs.exists, function(existing) {
                // array of existing files
                console.log(existing);
                // now assign the existing files to result array
                result = existing;
            });
            // should be the same as existing in callback function
            console.log(result);
        };
    

    no need for fs-extra. I think your issue is that async.filterLimit() does not return anything but executes a callback function, so just by assigning async.filterLimit() to a variable does not mean you get the result in there, you'll get undefined because the function does not return anything!

    EDIT: Adapted snippet from above based on @Jaromanda X's comment:

        const asyncFilter = require('async').filterLimit;
        const fs = require('fs');
    
        async function filterFiles(fileList) {
            let result = await asyncFilter(fileList, 5, fs.exists);
            // should contain only existing files
            console.log(result);
        };