1

Its simple 20 lines of code

const instaTouch = require('instatouch');
const vision = require('@google-cloud/vision');

const client = new vision.ImageAnnotatorClient();
process.env['GOOGLE_APPLICATION_CREDENTIALS']

// this returns images from instagram based on tag I provide, it returns promise.
// so far so good, I am getting the image URLs

const getMediaUrls = async (tag, limit) => {
  const options = { count: limit, mediaType: 'image' };
  const response = await instaTouch.hashtag(tag, options);
  let mediaUrls = response.collector.map((el) => el.display_url);

  if (mediaUrls !== undefined || mediaUrls.length != 0) return mediaUrls;
};

Here is the problem

const startScrap = (tag, labels, limit) => {
  let matchedMediaUrls = [];
  getMediaUrls(tag, limit)
    .then((mediaUrls) =>
      mediaUrls.forEach(async (mediaUrl) => {
        // send image url to google vision api and returns label
        const [result] = await client.labelDetection(mediaUrl);
        const mediaLabels = result.labelAnnotations;

       // I check if returned labels from vision api matches with any of the labels I asked for
       // if that the case I return the image, and populate matchedMediaUrls=[] array
        
       let labelsArr = mediaLabels.map((el) => el.description.toLowerCase());
        const matches = labelsArr.filter((el) => labels.includes(el));

        if (matches.length > 0) {
         // if I console.log() i find the array getting populated correctly but I don't know how to return it
          matchedMediaUrls.push(mediaUrl);
          console.log(matchedMediaUrls);
        }
      })
    )
    .catch((err) => console.log(err));
};

if I return it here, I get an empty array.

I picked nodejs yesterday. It might not be good question, but I really need help. I have no idea how to fix it, been trying for last 6 hours. Any help would be much appreciated.

pro noob
  • 13
  • 3
  • What is the error that you are getting while accessing `matchedMediaUrls` outside of for loop? – Avani Khabiya Apr 12 '21 at 08:47
  • I am not getting any errors, everything working properly, just that the matchedMediaUrls gets called before array get populated. so I get empty array in return if I call it from outside. – pro noob Apr 12 '21 at 08:51
  • @pronoob What do you mean by "*matchedMediaUrls gets called*"? Where are you trying to use that array in your code? – Bergi Apr 12 '21 at 09:05
  • I want to return matchedMediaUrls from the function. I will pass it to jade template via express route – pro noob Apr 12 '21 at 09:25
  • 1
    There is no return statement in the code above, where are you trying to return matchedMediaUrls? – Avani Khabiya Apr 12 '21 at 10:11

1 Answers1

0

I changed your functions to work with async/await I couldn't test it properly but let me know if it's not working

const instaTouch = require('instatouch');
const vision = require('@google-cloud/vision');

const client = new vision.ImageAnnotatorClient();
process.env['GOOGLE_APPLICATION_CREDENTIALS']

const getMediaUrls = (tag, limit) => {
    return new Promise(async (resolve, reject) => {
        const options = { count: limit, mediaType: 'image' };
        const response = await instaTouch.hashtag(tag, options);
        let mediaUrls = response.collector.map((el) => el.display_url);

        if (mediaUrls !== undefined || mediaUrls.length != 0) resolve(mediaUrls);
    });

};

And this is where you call getMediaUrls function


const startScrap = async (tag, labels, limit) => {

    var matchedMediaUrls = [];

    var mediaUrls = await getMediaUrls(tag, limit);


    for (let mediaUrl of mediaUrls) {

        const [result] = await client.labelDetection(mediaUrl);
        const mediaLabels = result.labelAnnotations;

        let labelsArr = mediaLabels.map((el) => el.description.toLowerCase());
        const matches = labelsArr.filter((el) => labels.includes(el));

        if (matches.length > 0) {
            matchedMediaUrls.push(mediaUrl);
            console.log(matchedMediaUrls);
        }
    }

    return matchedMediaUrls;
}

Murat Colyaran
  • 2,075
  • 2
  • 8
  • 27