Home > OS >  Cannot read properties of undefined (reading '$eval') randomly popping in puppeteer script
Cannot read properties of undefined (reading '$eval') randomly popping in puppeteer script

Time:10-04

I have a nodejs script which use Puppeteer and works well. The code is basically this :

//Load href to visit into each tab
tabs = [];
var idxTab=0;
for(let hrefToVisit of hrefsToVisit) {
          tabs.push(await browser.newPage());
          await tabs[idxTab].goto(hrefToVisit, {waitUntil: 'domcontentloaded'});
          idxTab  ;
}

while (true) {

  ...  

  //Refresh all tabs
  var promises = [];
  for (let tab of tabs ) {
    promises.push(tab.reload());
  }

  await Promise.all(promises);    

  try{ 

    let allNews = '';
    let firstNews = '';
    let pseudo = '';

    //Get the first news on the page
    allNews = await tab.$$("article.news");
    await tab.waitForTimeout(5000);
    firstNews = allNews[0];
    
    //Get the pseudo of this first news
    pseudo = await firstNews.$eval('.user.userInfo span', s => s.textContent.trim());
    console.log(new Date(), 'Pseudo : ', pseudo, '...');

    //Log HTML content for debug
    console.log('html when all ok : ');
    let bodyHTML = await tab.evaluate(() => document.body.innerHTML);
    console.log(bodyHTML);
    await tab.screenshot({path: 'ok.png'});
  }catch (err){
    console.log('html when not ok : ');
    let bodyHTML = await tab.evaluate(() => document.body.innerHTML);
    console.log(bodyHTML);
    await tab.screenshot({path: 'ko.png'});
    console.log(err);
  }

  ...

}

The problem is, I have 30% of time this error :

TypeError: Cannot read properties of undefined (reading '$eval')
    at main (script.js:327:40)

Sometimes it runs ok, sometimes don't.

So I logged html when it's ok and when it's not. I also made a screenshot.

Both HTML and screenshot are the same, the page is loaded and the elements are present in the html, so why I can't "eval" them ?

The part :

await tab.waitForTimeout(5000);

make the things a little better sometimes, but not enough. I tried to use other strategy, like using :

await waitForSelector('article.news');

Before evaluate anything, but it doesn't change anything, it's even worth because it doesn't wait a lot (the element is quickly displayed so it passed true). Waiting 5s each time seems a little better, but even if I put 10s, sometimes it failed anyway...

How can I debug this, to find the problem ?

CodePudding user response:

Weirdly, after fixing some little thing with ESLINT help (thx to ggorlen), it seems to work better.

I used "destructuring" to get the first news, and put back the "await tab.waitForSelector..." instead of waiting 5000ms :

let firstNews;
let otherNews;
let pseudo = '';
...
await tab.waitForSelector('article.news', { timeout: 5000 });
[firstNews, ...otherNews] = await tab.$$('article.news');
  • Related