Question

I know this is probably a duplicate but I just can't figure out how to do it (trust me i've searched, i've tried to fiddle around with the code). I have the following code which is building a table of files that you drag and dropped in to the app.

function CreateTrackTable (data, length) {

    var fs = require('fs'),
        mm = require('musicmetadata'),
        i  = 0;

    for (i; i < length; ++i) { 

        var mimeType = data.dataTransfer.files[i].type;

        if (mimeType == "audio/mp3" || mimeType == "audio/x-m4a"){

                FilePath = data.dataTransfer.files[i].path;
                var parser = mm(fs.createReadStream(FilePath));

            parser.on('metadata',  function (result) {

                if (result.picture.length == 0) {
                    $("#track-table").append('<tr path="'+ FilePath +'"><td></td></tr>');
                }else{
                    var picture = base64ArrayBuffer(result.picture[0].data);
                    $("#track-table").append('<tr path="'+ FilePath +'"><td></td></tr>');     
                }
            });
        }
    } 
}

The Problem is that the FilePath variable is accessible however it "prints-out" always the same path, not the one respected to the loop i.

The app is builded with nodo-webkit everything quite works and this is the only problem I can't figure out.

Thanks for the help!

Was it helpful?

Solution

Each function created inside the loop closes over the same FilePath (i.e. they don't each get their own copy), which means that they'll each see whatever value that variable has whenever they execute. To make this work how you expect, you need to arrange it so that they do each get their own copy. Since JavaScript variables are scoped to the nearest enclosing function, the way to do that is to wrap the function creation in an immediately-invoked function that receives the desired value as an argument:

(function(FilePath) {
    parser.on('metadata',  function (result) {
        if (result.picture.length == 0) {
            $("#track-table").append('<tr path="'+ FilePath +'"><td></td></tr>');
        } else {
            var picture = base64ArrayBuffer(result.picture[0].data);
            $("#track-table").append('<tr path="'+ FilePath +'"><td></td></tr>');     
        }
    });
})(FilePath);

In this case, each new function closes over a new FilePath, which produces the wanted result.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top