Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does an ElementHandle differ from a DOM Element?

The documentation on page.$(selector) says it returns a promise containing an ElementHandle.

But the documentation on ElementHandle is a bit lacking.

It says it "represents a DOM element", but what does that really mean? And if does represent the DOM, why can't the contents of the ElementHandle be inspected?

It also says, "prevents DOM element from garbage collection unless the handle is disposed." Why would a DOM element get garbage collected if the browser is still on the page?


This came up because I thought it'd be simple to grab the text from an element on the page, so I tried,

const text = await page.$('#text').textContent;

which returned undefined. So I tried,

const text = await page.$('#text').textContent();

which threw an error.

Turns out the correct way is

const text = await page.evaluate(() => document.querySelector('#text').textContent);
like image 451
Atav32 Avatar asked May 08 '18 21:05

Atav32


People also ask

What is ElementHandle?

ElementHandle prevents the DOM element from being garbage-collected unless the handle is disposed. ElementHandles are auto-disposed when their origin frame gets navigated. ElementHandle instances can be used as arguments in Page.

What is a JSHandle?

JSHandle prevents the referenced JavaScript object being garbage collected unless the handle is disposed . JSHandles are auto-disposed when their origin frame gets navigated or the parent context gets destroyed. JSHandle instances can be used as arguments in page.


1 Answers

With ElementHandle can you still access to properties like textContent but in "Puppeteer way". Firstly you must .getProperty() on ElementHandle, and after that convert it to .jsonValue(). Remember that all this operations returns poromises so you should await on all of them like this:

await (await (await page.$('#text')).getProperty('textContent')).jsonValue();

Here is full working example:

const puppeteer = require('puppeteer');

const html = `
<html>
  <body>
    <div id="text">Sample content</div>
  </body>
</html>`;

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto(`data:text/html,${html}`);

  const text = await page.evaluate(() => document.querySelector('#text').textContent);
  const text2 = await (await (await page.$('#text')).getProperty('textContent')).jsonValue();

  console.log(text);
  console.log(text2);

  await browser.close();
})();
like image 128
Everettss Avatar answered Oct 03 '22 06:10

Everettss