2

I'm trying to make a proper asynchronous function which contains a callback but apparently my way of doing this doesn't work.

Here's my code:

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

var tmp = 0;
var i = 0;

function getFilesByExtArgs(dir, ext, function(err)){
    if (err){
        console.log("Error: " + err.code + " (" + err.message + ")");
        return;
    }
    else{
        fs.readdir(dir, function (err, data){
                while (i <= data.length){
                    if (path.extname(data[i]) == ('.' + ext))
                        console.log(data[i]);
                    i++;
                }
            });
    }
}
module.exports = getFilesByExtArgs;

When I try to launch that, I get the following error:

function getFilesByExtArgs(dir, ext, function(err)){
                                     ^^^^^^^^
SyntaxError: Unexpected token function

How can I make it "the node way" ?

2 Answers 2

2

You just need a parameter for your function and then call it. You can then expect the caller of the function to provide a callback function to that parameter.

Another mistake is your use of the while loop. You're better off if you use a for loop and declare the i variable inside it. That way, you can make sure that no other function will touch the i variable.

Also, instead of i <= data.length you need i < data.length. If you access data[data.length] you will get out of range.

Of course inside the getFilesByExtArgs function you may want to check if the parameter really is a function. You can do it with the typeof operator. For example:

if (typeof(callback) !== "function") {
    throw new Error("The callback parameter must be a function");
}

Here's your code, with a fixed syntax: I assume you want a callback not just for errors, but for actual results as well? Then you can do it like this:

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

function getFilesByExtArgs (dir, ext, callback) {
    if (typeof(callback) !== "function") {
        throw new Error("The callback parameter must be a function");
    }
    fs.readdir(dir, function (err, data) {
        if (err) {
            return callback(err);
        }
        var results = [];
        for (var i = 0; i < data.length; i++) {
            if (path.extname(data[i]) == ('.' + ext)) {
                results.push(data[i]);
            }
        }
        callback(null, results);
    });
}

You can call it like this:

getFilesByExtArgs('/my/file/path', 'txt', function (err, results) {
    if (err) {
        // Something bad happened
        console.log("an error occoured!");
        return;
    }

    // You can use the results array
    console.log("printing the results:");
    for (var i = 0; i < results.length; i++) {
        console.log(i, results[i]);
    }
});

Hope this helps.

Sign up to request clarification or add additional context in comments.

7 Comments

I don't understand what should I right after the if when I call my function, right now, when I call the function I have: getFilesByExtArgs(process.argv[2], process.argv[3], function(results){ if (results instanceof Error) console.log("Error"); });
@Mehdi You should put some error handling in there. What do you want to do if something bad happens?
I just want to right an error message if something is wrong, otherwise display my list normally.
This is not "the node way", the callback should have separate parameters for the error and for the return values.
@andrezsanchez I think that's only a matter of opinion, but I edited my answer to suit your way.
|
1

You don't define functions as parameters in this way, you simply provide a named parameter which you then invoke as a function e.g.

function getFilesByExtArgs(dir, ext, callback){
    if (/* something bad */) {
        callback('Error thrown');
    } else {
        callback();
    }
}
...
getFilesByExtArgs('/my/file/path', '.txt', function(err) {
    if (err) throw err;
    ...
});

In your example, I presume what you are trying to do is something like

function getFilesByExtArgs(dir, ext, callback){
    fs.readdir(dir, function(err, data) {
        if (err) {
            callback(err);
        } else {
           while (i <= data.length) {
               if (path.extname(data[i]) == ('.' + ext))
                   console.log(data[i]);
               i++;
           }
           callback();
        }
    });
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.