1

I'm using Jimp to manipulate some photos.

I have an array with photos. Like this:

var images = ['.../pic-1.jpg', '.../pic-2.jpg', '.../pic-3.jpg', '.../pic-4.jpg'];

And this is the code for manipulating them:

images.forEach(function(image){
  jimp.read(image, function(err, img){
    img.quality(90, function(){
      console.log("done with this image!");
    });
  });
});

This works nice it logs when each image is done. However, it's blocking the code and if I try this:

var processed = 0;

images.forEach(function(image){
  jimp.read(image, function(err, img){
    img.quality(90, function(){
      processed++;
      document.querySelector('p').textContent = 'processed images: ' + processed;
    });
  });
});

it doesn't update the text until all the images are processed. How can I work this around so I can update the text each time an image gets processed?

5
  • do the work in a timeout. That will insure it occurs in the next event. Commented Mar 24, 2017 at 19:11
  • i don't understand sorry, how so? Commented Mar 24, 2017 at 19:18
  • I don't see any blocking in this code. Inside forEach all calls seem to be async. Commented Mar 24, 2017 at 19:19
  • @Ananth I know, that's why I don't know what's causing it, I'm trying to debug it but nothing works Commented Mar 24, 2017 at 19:22
  • The only thing that .quality() seems to do is set an instance property. Commented Mar 24, 2017 at 19:54

1 Answer 1

0

It may seem like this because everything happens in parallel instead of in sequence, or maybe indeed the most time is spent in img.quality() and it's a CPU-intensive task that blocks the main thread.

You can try changing this:

images.forEach(function(image){
  jimp.read(image, function(err, img){
    img.quality(90, function(){
      processed++;
      document.querySelector('p').textContent = 'processed images: ' + processed;
    });
  });
});

to something like this:

let processed = 0;
let f = () => {
  jimp.read(images[processed], function(err, img){
    img.quality(90, function(){
      processed++;
      document.querySelector('p').textContent = 'processed images: ' + processed;
      if (processed < images.length) setImmediate(f);
    });
  });
};

You can also change setImmediate to setTimout with some timeout value that would let the UI thread to draw on the screen what it needs to draw. You could even use the window.requestAnimationFrame() for that.

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

1 Comment

Your statement about setImmediate is not quite correct. setImmediate will be added to the end of the event list. Draw events will happen before it You do not need to use setTimeout to let the UI draw.

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.