Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
729 views
in Technique[技术] by (71.8m points)

javascript - How can I dynamically inject functions to evaluate using Puppeteer?

I am using Puppeteer for headless Chrome. I wish to evaluate a function inside the page that uses parts of other functions, defined dynamically elsewhere.

The code below is a minimal example / proof. In reality functionToInject() and otherFunctionToInject() are more complex and require the pages DOM.

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(someURL);       

var functionToInject = function(){
    return 1+1;
}

var otherFunctionToInject = function(input){
    return 6
}

var data = await page.evaluate(function(functionToInject, otherFunctionToInject){
    console.log('woo I run inside a browser')
    return functionToInject() + otherFunctionToInject();
});

return data

When I run the code, I get:

Error: Evaluation failed: TypeError: functionToInject is not a function

Which I understand: functionToInject isn't being passed into the page's JS context. But how do I pass it into the page's JS context?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can add function to page context with addScriptTag:

const browser = await puppeteer.launch();
const page = await browser.newPage();

function functionToInject (){
    return 1+1;
}

function otherFunctionToInject(input){
    return 6
}

await page.addScriptTag({ content: `${functionToInject} ${otherFunctionToInject}`});

var data = await page.evaluate(function(){
    console.log('woo I run inside a browser')
    return functionToInject() + otherFunctionToInject();
});

console.log(data);

await browser.close();

This example is a dirty way of solving this problem with string concatenation. More clean would be using a url or path in the addScriptTag method.


Or use exposeFunction (but now functions are wrapped in Promise):

const browser = await puppeteer.launch();
const page = await browser.newPage();

var functionToInject = function(){
    return 1+1;
}

var otherFunctionToInject = function(input){
    return 6
}

await page.exposeFunction('functionToInject', functionToInject);
await page.exposeFunction('otherFunctionToInject', otherFunctionToInject);

var data = await page.evaluate(async function(){
    console.log('woo I run inside a browser')
    return await functionToInject() + await otherFunctionToInject();
});

console.log(data);

await browser.close();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...