简体   繁体   中英

JavaScript promise won't resolve or reject, it just blocks for some reason

I'm writing a node script, which is supposed to order images by a score value, calculated by a function called getImageScore() . This score takes quite some time to be calculated, therefore I created a promise ( promiseImageScore ) that would return the score value. After getting the promised value by the promiseImageScore promise, the program would log the name of the image and its score . Despite creating a promise for the score values, they still come back as undefined . I observed the promises would never finish, they just always remain in pending state. I tried tracing what's actually happening in the getImageScore() function, by logging some messages through the function and, as expected, those logs stop at some point, but I cannot get why this happens. Here is the full program:

const fs = require('fs');
const { resolve } = require('path');
const { reject } = require('q');
const { Console } = require('console');
const gm = require('gm').subClass({imageMagick: true});
const PNG = require("pngjs").PNG;
let pathToFolder = '/home/eugen/Pictures/wallpapers1';
let pathToImage = '';

let promiseImageScore = new Promise((resolve, reject) => {
  resolve(getImageScore());
});

function getImageScore() {
  console.log('entered this promise....');
  let img = gm(pathToImage);
  // Get the PNG buffer
  img.toBuffer("PNG", (err, buff) => {
    if (err) return new Error(err);
    console.log('got buffer...');
    // Get the image size
    img.size((err, size) => {
      if (err) {
        console.log(err);
        return new Error(err);
      }
      console.log('got image size...');
      // Parse the PNG buffer
      let str = new PNG();
      str.end(buff);

      // After it's parsed...
      str.on("parsed", buffer => {
        // Get the pixels from the image
        let idx, score = 0, rgb = {r: 0, g: 0, b: 0};

        for (let y = 0; y < size.height; y++)
          for (let x = 0; x < size.width; x++) {
            idx = (size.width * y + x) << 2;
            rgb.r = buffer[idx];
            rgb.g = buffer[idx + 1];
            rgb.b = buffer[idx + 2];
            score += (rgb.r + rgb.g + rgb.b) / 765;
          }
          console.log('one promised finished...');
          return score / (size.height * size.width);
      });
      str.on("error", e => {
        return new Error(e);
      });
    });
  });
}

// see which images are to be found in the specificd directory
fs.readdir(pathToFolder, function (err, files) {
    if (err) return console.log('Unable to scan directory: ' + err);
    console.log('files in directory:\n');
    files.forEach(function (file) {
        pathToImage = pathToFolder + '/' + file;
        //showImageScore();
        promiseImageScore
        .then(imageScore => {
          console.log(file + ' has a score of ' + imageScore);
        })
        .catch(e => {
          throw e;
        })
    });
});

Here is the output of the code:

entered this promise....
files in directory:

Boats_Thailand_Sea_Crag_Nature_8000x5224.jpg has a score of undefined
Wallpaper_8K_0_7680x4320.jpg has a score of undefined
Water_mountains_landscapes_nature_snow_valley_rocks_switzerland_rivers_3840x2400.jpg has a score of undefined
Waterfalls_USA_Crag_Trees_Hocking_Hills_State_Park_Ohio_Nature_10929x5553.jpg has a score of undefined
cats_blue_eyes_animals_pets_4288x2848.jpg has a score of undefined
cats_blue_eyes_animals_pets_4288x2848.png has a score of undefined
city_night_panorama_117682_3840x2160.jpg has a score of undefined
starry_sky_tree_night_sky_119989_1920x1080.jpg has a score of undefined
got buffer...

After the got buffer... log, the program keeps running, never stopping, apparently doing nothing.

Your code is not working with promises correctly. You need to make several changes:

  1. Pass the resolve and reject to getImageScore :
const promiseImageScore = new Promise((resolve, reject) => {
  // You need to pass resolve and reject to getImageScore
  getImageScore(resolve, reject);
});
  1. Use resolve and reject in getImageScore :
// For example
img.toBuffer("PNG", (err, buff) => {
  // If you get an error you need to call reject and return from the function
  // You will need to do the same for img.size((err, size) => {})
  // and for str.on("error", e => {})
  if (err) return reject(err);

  // Then when you have your result and there were no errors,
  // you will need to call resolve with the result
  resolve(score / (size.height * size.width));
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM