0

I am working with puppeteer and this is the abstract concept I want to resolve:

From an array of URLs, find all images and get BoxModel

// URLS, easy step
const urls = ['google.com', 'amazon.com', 'github.com', 'so on'];

// This is basically a browser tab from chromiumn a.k.a. puppeteer
const page = const page = (await browser.pages())[0];

// Add magic function

magic1(page) // all those listen from different page events
magic2(page)
magic3(page)
imageMagic(page) // this one wait for 'load' event


// inside imageMagic function

    page.on('load', async function () { // wait untill load to find images
        try {
            const imgs = await page.$$('img');
            for await (const itm of imgs) {
                // DO things with each image
            }
        } catch (e) {
            console.error(e);
        }
    });

Then the main process is some near to below:

async function ultraPowerMagicFunction(url){
      try {
        await magic(page)
        await magic2(page)
        await magic3(page)
        await imageMagic(page)
    
        const navigate = page.waitForNavigation({
          waitUntil: 'load',
        });
    
        await page.goto(url);
    
        await navigate;

        // Here I need to wait until imageMagic finish
        // nextExecution()
      } catch (e){
        console.error('PROBLEM IN MAIN FLOW:', e);
      }
}

Now as final step, I need to do this for each item

for await (cont url of urls) {
   await ultraPowerMagicFunction(url);
}

In resume, how to wait until event triggered (load) finish their async method before go to next iteration?.

Thanks in advance.

elporfirio
  • 306
  • 2
  • 15
  • 1
    [`await once(page, 'load')`](https://nodejs.org/api/events.html#events_events_once_emitter_name) should do in a modern nodejs. – Bergi Sep 11 '20 at 22:03
  • Yup it does, but I need to wait a process on load before next step. – elporfirio Sep 13 '20 at 01:54
  • What do you mean by "*wait a process on load*"? You just waited for the load, now do your processing. – Bergi Sep 13 '20 at 13:37
  • This is to do web scrappin, "load" is when page has been loaded, like DOM on any webpage. But every iteration I have to change requested URL, then every item on iteration has a "load event" – elporfirio Sep 14 '20 at 18:12

1 Answers1

-1

You can use the Promise constructor so that the async function can signal when it's done:

return new Promise((res, rej) => {
    page.on('load', async function () { // wait untill load to find images
        try {
            const imgs = await page.$$('img');
            for await (const itm of imgs) {
                // DO things with each image
            }
            res();
        } catch (e) {
            rej(e);
        }
    });
})
Tamás Sallai
  • 3,195
  • 1
  • 14
  • 25
  • Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi Sep 13 '20 at 13:36