0

I am trying to use a node-image-scraper package to scrape some images from a webpage, then return the array of images to the client in Meteor. However, I currently have no idea how this would work given the event driven nature of the pack.

var imageScraper = new imagescraper();
var images;

Meteor.methods({
    scrapeImgs(url){
        imageScraper.on('image', (image) => {
           images.push(image);
        });

        images = [];
        imageScraper.address = url;
        imageScraper.scrape();

        imageScraper.on('end', () => {
            return images; //does not work
        });

        return images; // returns an empty array
    },
});

Returning images from the event does not work, and returning images outside returns an empty array. Is there any way to make this work? Or is it fundamentally not possible given the circumstances? How would this be done if I need to return the full set of images to the client?

Luke Tan
  • 2,048
  • 2
  • 13
  • 21
  • 1
    Possible duplicate of [How to return from an async function](https://stackoverflow.com/questions/5809300/how-to-return-from-an-async-function) – Titus Mar 11 '18 at 07:05
  • Unfortunately, that question was never answered. The author said he contacted the writer of the 3rd party script and he provided him with a solution, which he never did share. – Luke Tan Mar 11 '18 at 08:49
  • 1
    The problem is that you're trying to return from an async function, there are a lot of answers on stackoverflow that address that problem, like this: https://stackoverflow.com/a/14220323/1552587 for example – Titus Mar 11 '18 at 08:53
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – coagmano Mar 11 '18 at 09:09
  • Meteor wise it is basically the same problem as https://stackoverflow.com/questions/47017782/meteor-promises-in-accounts-oncreateuser/ – coagmano Mar 11 '18 at 09:19
  • 1
    Found the answer here: https://stackoverflow.com/questions/42475006/image-scraper-nodejs-how-to-send-callback-function-to-result-array – Luke Tan Mar 11 '18 at 10:37
  • 1
    Possible duplicate of [Meteor: Calling an asynchronous function inside a Meteor.method and returning the result](https://stackoverflow.com/questions/12569712/meteor-calling-an-asynchronous-function-inside-a-meteor-method-and-returning-th) – Christian Fritz Mar 12 '18 at 18:00

1 Answers1

1

Simply return a promise:

Meteor.methods({
scrapeImgs(url){
    let images = []; // define vars
    imageScraper.on('image', (image) => {
       images.push(image);
    });

    imageScraper.address = url;
    imageScraper.scrape();

    return new Promise((resolve, reject) => {
        imageScraper.on('end', () => {
            resolve(images); // This will only trigger on end
            // Check end really triggers when expected
            // Don't use return on callbacks unless terminating explicitely
        });
        // Guessing it has an error event...
        imageScraper.on('error', (err) => {
            reject(new Meteor.Error(err));
            // Reject with Meteor.Error since these are caught and sanitized 
        })
    });
    // returns an empty array as array was populated on event callback, not on current process loop.
},
});

Depending on your front end call, you can either access the value directly or access .then(), just check that on front end :)

Gabriel Balsa Cantú
  • 1,954
  • 1
  • 14
  • 11