Using Puppeteer to run a function with a callback: not working

I’m having trouble with Puppeteer. I’m trying to run a function that has a callback, but it’s not working as expected. Here’s what I’m dealing with:

On the page I’m scraping, there’s a listener like this:

DataBase.onReady().run(function(db) {
  // DataBase can do stuff here
})

In my Puppeteer script, I’m trying to get the ready database like this:

try {
  const dbConnection = await page.evaluate('DataBase.onReady()');
  const output = await page.evaluate(db => db.run, function(data) {
    console.log(JSON.stringify(data));
    // More stuff with the callback
  }, dbConnection);
  console.log('output', JSON.stringify(output));
} catch (error) {
  console.log('evaluate error', error);
} finally {
  console.log('done');
}

But it’s not working. The callback never fires. I’m sure the page I’m scraping works fine. Any ideas what I’m doing wrong here? I’m really stuck and could use some help.

hey mate, i’ve had similar issues with puppeteer. looks like ur trying to pass a callback between contexts which doesn’t work well. try using page.exposeFunction() to create a bridge between puppeteer and the page. then u can call that function from within page.evaluate(). hope this helps!

I’ve encountered this problem before, and it can be frustrating. The issue lies in how Puppeteer handles context switching between the Node.js environment and the browser.

Instead of trying to pass callbacks directly, I’d suggest using Promises. You can modify your code to return a Promise from the page.evaluate() call, which resolves when the database is ready. Here’s a rough example of how you might approach this:

const dbReady = await page.evaluate(() => {
  return new Promise((resolve) => {
    DataBase.onReady().run(function(db) {
      resolve(db);
    });
  });
});

console.log('Database is ready:', dbReady);

// Now you can use the ready database for further operations
const result = await page.evaluate((db) => {
  // Perform operations with the database
  return db.someOperation();
}, dbReady);

This approach has worked well for me in similar situations. It keeps the asynchronous nature of the operation while allowing you to wait for the result in your Puppeteer script.