1

Trying to write a function that can be exported so I can call on it in various places and easily pass it images.

I've tried various ways of incorporating the functions as async and using await wherever needed. Just don't seem to be getting it quite right. I have removed the attempted async/await functionality so you can see how the code looks beforehand.

const getPixels = require("get-pixels");

const imgLink = 'https://upload.wikimedia.org/wikipedia/commons/8/8a/LGBT_Rainbow_Flag.png';

exports.analyzeImg = imgLink => {
  getPixels(imgLink, (err, pixels) => {
    if (err) {
      console.log("Bad image path");
      return;
    }

    const copyPixelArr = [...pixels.data];

    const rgbExtraction = grid => {
      const allRed = [];
      const allGreen = [];
      const allBlue = [];
      const allWhite = [];

      for (let i = 0; i < grid.length; i += 4) {
        allRed.push(grid[i]);
      }
      for (let i = 1; i < grid.length; i += 4) {
        allGreen.push(grid[i]);
      }
      for (let i = 2; i < grid.length; i += 4) {
        allBlue.push(grid[i]);
      }
      for (let i = 3; i < grid.length; i += 4) {
        allWhite.push(grid[i]);
      }

      const avgRed =
        allRed.reduce((acc, val) => {
          acc += val;
          return acc;
        }, 0) / allRed.length;
      const avgGreen =
        allGreen.reduce((acc, val) => {
          acc += val;
          return acc;
        }, 0) / allGreen.length;
      const avgBlue =
        allBlue.reduce((acc, val) => {
          acc += val;
          return acc;
        }, 0) / allBlue.length;
      const avgWhite =
        allWhite.reduce((acc, val) => {
          acc += val;
          return acc;
        }, 0) / allWhite.length;

      return {
        r: avgRed,
        g: avgGreen,
        b: avgBlue,
        w: avgWhite
      };
    };
    const data = rgbExtraction(copyPixelArr);
    console.log(data);
    return data;
  });
};

Currently the console.log(data) returns what I want it too however the return data; is undefined as it's not waiting for the other functions to run before it tried to return.

  • The most simple way would be allowing to pass a callback to your function and then calling this callback with your asynchronous result. Alternatively, you could have your function return a Promise, which basically represents an asynchronous / deferred result. – m90 Apr 10 '19 at 10:45
  • Have you see webworker. Details: https://www.w3schools.com/html/html5_webworkers.asp – Chris P Apr 10 '19 at 10:46
  • 1
    The return value of `analyzeImg` is undefined because `analyzeImg` **has no return statement**. – Quentin Apr 10 '19 at 10:47
  • Add `return getPixels(imgLink, (err, pixels) => {` – random Apr 10 '19 at 10:53
  • @Quentin returning data in analyzeImg is useless when data is undefined within the inner function. copyPixelArray takes a few seconds to populate therefore the return happens before its finished. The console log then prints a good second or two after the 'return data' statement comes back as undefined. – Danny Caddick Apr 10 '19 at 11:03
  • @DannyCaddick — My point is that `return data;` is returning the value you want, but not to where you seem to think it was. The duplicate covers dealing with async functions. – Quentin Apr 10 '19 at 11:08
  • @Quentin I don't quite understand what you're trying to say. I know how to write an async/promise into a function. I just can't work out how to do it with multiple nested functions. That link you declared as 'duplicate' doesn't really help me much. – Danny Caddick Apr 10 '19 at 11:13
  • @DannyCaddick — The nested functions are a red herring. Only getPixels is async. If you moved `return data;` down one line, it would be identical to code structure of the duplicate question (and the problem is the same as the duplicate, your attempt to solve it is just very subtly different and failing for the same reason). – Quentin Apr 10 '19 at 11:15

0 Answers0