Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 611 Vote(s) - 3.46 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to pass a function in Puppeteers .evaluate() method

#1
Whenever I try to pass a function, like this:

var myFunc = function() { console.log("lol"); };

await page.evaluate(func => {
func();
return true;
}, myFunc);

I get:

(node:13108) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Evaluation failed: TypeError: func is not a function
at func (<anonymous>:9:9)
(node:13108) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Why? How to do it correctly?

Thank you!

€: let me clarify: I am doing it this way because I want to find some DOM elements first and use them inside of that function, more like this (simplified):

var myFunc = function(element) { element.innerHTML = "baz" };

await page.evaluate(func => {
var foo = document.querySelector('.bar');
func(foo);
return true;
}, myFunc);
Reply

#2
Similar problems have been discussed in a puppeteer [issue][1].

There are several way to deal with your problem. First rule is to keep it simple.

# Evaluate the function

This is the fastest way to do things, you can just pass the function and execute it.

await page.evaluate(() => {
var myFunc = function(element) { element.innerHTML = "baz" };
var foo = document.querySelector('.bar');
myFunc(foo);
return true;
});

# Expose the function beforehand

You can expose the function beforehand using a page.evaluate, or a page.addScriptTag

// add it manually and expose to window
await page.evaluate(() => {
window.myFunc = function(element) { element.innerHTML = "baz" };
});

// add some scripts
await page.addScriptTag({path: "myFunc.js"});

// Now I can evaluate as many times as I want
await page.evaluate(() => {
var foo = document.querySelector('.bar');
myFunc(foo);
return true;
});

# Use ElementHandle

## page.$(selector)
You can pass an element handle to .evaluate and make changes as you seem fit.

const bodyHandle = await page.$('body');
const html = await page.evaluate(body => body.innerHTML, bodyHandle);

## page.$eval

You can target one element and make changes as you want.

const html = await page.$eval('.awesomeSelector', e => {
e.outerHTML = "whatever"
});

The trick is to [read the docs][2] and keep it simple.


[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply

#3
**Pass function with parameter**

// add it manually and expose to window


await page.evaluate(() => {
window.myFunc = function(element) { element.innerHTML = "baz" };
});

// and then call function declared above


await page.evaluate((param) => {
myFunc (param);
}, param);

Reply

#4
You cannot pass a function directly into `page.evaluate()`, but you can call another special method (`page.exposeFunction`), which expose your function as a global function (also available in as an attribute of your page `window` object), so you can call it when you are inside `page.evaluate()`:
```lang-js
var myFunc = function() { console.log("lol"); };
await page.exposeFunction("myFunc", myFunc);

await page.evaluate(async () => {
await myFunc();
return true;
});
```

Just remember that `page.exposeFunction()` will make your function return a `Promise`, then, you need to use `async` and `await`. This happens because your function will not be [running inside your browser](

[To see links please register here]

), but inside your `nodejs` application.

1. [exposeFunction() does not work after goto()](

[To see links please register here]

)
1.

[To see links please register here]

1.

[To see links please register here]

1. [exposeFunction remains in memory?](

[To see links please register here]

)
1.

[To see links please register here]

1.

[To see links please register here]

1. [allow to pass a parameterized funciton as a string to page.evaluate](

[To see links please register here]

)
1. [Functions bound with page.exposeFunction() produce unhandled promise rejections](

[To see links please register here]

)
1.

[To see links please register here]

1.

[To see links please register here]

Reply

#5


// External function to run inside evaluate context
function getData() {
return document.querySelector('title').textContent;
}

function mainFunction(url, extractFunction){
let browser = await puppeteer.launch({});
let page = await browser.newPage();

await page.goto(url);

let externalFunction = Object.assign(extractFunction);

let res = await this.page.evaluate(externalFunction)

console.log(res);
}


// call it here
mainFunction('www.google.com',getData);
Reply

#6
I like [evaluateOnNewDocument](

[To see links please register here]

) because I want to ensure my script code is ran before anything else.

For example, if looking for total-blocking-time web vitals:

```javascript
const perfObserver = () => {
// Important that you don't run for this URL.
if (window.location.href === 'about:blank') return;

window.totalBlockingTime = 0;

console.log(window.location.href);
console.log('TBT', totalBlockingTime);

const observer = new PerformanceObserver(function (list) {
let perfEntries = list.getEntries();
for (const perfEntry of perfEntries) {
let longtask = perfEntry.duration - 50
if (longtask) console.log(perfEntry);
totalBlockingTime += longtask;
}
console.log({ totalBlockingTime });
});
observer.observe({ type: "longtask", buffered: true });
};


const browser = await puppeteer.launch({
headless: true,
devtools: false
});

const page = await browser.newPage();

await page.evaluateOnNewDocument(perfObserver);

await page.goto("https://stackoverflow.com/");

const performance = await page.evaluate(() => window.totalBlockingTime);

console.log(performance);

await browser.close();

```

You can also pass arguments into the function from your parent scope. See docs link above.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through