J. Doe
J. Doe

Reputation: 33

javascript shows output of only last iteration of for loops with promise object inside

I wrote a node.js script to use jimp to get all image files from a directory, (which I take as input), run some manipulations on that and then save them in the target directory (another input) as filename.suffix.extension. I take suffix also as input.

But I only see the last file from the list that I collect as to be present in the target directory.

// imports
var Jimp = require('jimp');
const fs = require('fs')

// inputs
dir = process.argv[2]
target = process.argv[3]
suffix = process.argv[4]

// collect files
let dirCont = fs.readdirSync( dir );
const files = dirCont.filter( ( elm ) => /.*\.(png|jpg)/gi.test(elm) );

// run jimp on each file and write to target directory
for (file in files)
{  
    target_file = target+files[file].replace(/\.[^/.]+$/, "")+'.'+suffix+files[file].match(/\.[^/.]+$/)
    Jimp.read(dir+'/'+files[file]).then(function (file) {
        return file.resize(256, 256)     // resize
             .quality(60)                 // set JPEG quality
             .greyscale()                 // set greyscale
             .write(target_file); // save
    })

}

I run the entire thing using grunt.

following up from this question, things that I tried:

but still pretty much not working

Immediately-Invoked Function Expression

var Jimp = require('jimp');
const fs = require('fs')

dir = process.argv[2]
target = process.argv[3]
suffix = process.argv[4]
let dirCont = fs.readdirSync( dir );
const files = dirCont.filter( ( elm ) => /.*\.(png|jpg)/gi.test(elm) );

for (file in files)
{
    (function(index) {
    console.log("index: "+index)
    target_file = target+files[index].replace(/\.[^/.]+$/, "")+'.'+suffix+files[index].match(/\.[^/.]+$/)
    Jimp.read(dir+'/'+files[index]), function (err, filee) {
             if (err) throw err;
             filee.resize(256, 256)     // resize
             .quality(60)                 // set JPEG quality
             .greyscale()                 // set greyscale
             .write(target_file); // save
    }
    })(file);

}

Result:

Still only the last file is written

Function.prototype.bind

var Jimp = require('jimp');
const fs = require('fs')

dir = process.argv[2]
target = process.argv[3]
suffix = process.argv[4]
let dirCont = fs.readdirSync( dir );
const files = dirCont.filter( ( elm ) => /.*\.(png|jpg)/gi.test(elm) );
var funcs = {}
for (file in files)
{
    console.log(file)
    console.log(files[file])

    target_file = target+files[file].replace(/\.[^/.]+$/, "")+'.'+suffix+files[file].match(/\.[^/.]+$/)
    funcs[file] = Jimp.read(dir+'/'+files[file]), function (err, filee) {
        return filee.resize(256, 256)     // resize
             .quality(60)                 // set JPEG quality
             .greyscale()                 // set greyscale
             .write(target_file); // save
    }.bind(this, file)

}

for (var j = 0; j < 3; j++) {
  funcs[j]();
}

Result:

Error message:

  funcs[j]();
          ^
TypeError: funcs[j] is not a function

I discovered it is a promise object

forEach implementation

still only the last iteration was printed

Can anyone help me on this?

Upvotes: 0

Views: 196

Answers (1)

dave
dave

Reputation: 64705

The issue is that target_file, in each of these, is a shared variable (each iteration is modifying the same one). Just change:

target_file = 

to

let target_file = 

or

const target_file = 

and you should be fine.

Upvotes: 2

Related Questions