How to access global variables in puppeteer

Viewed 3363

In this example code, when it reads the array contactList and j it says both are not defined, what is wrong?


const { join } = require('path');
const puppeteer = require('puppeteer');

(async () => {

    // 1. Launch the browser
    const browser = await puppeteer.launch({   
          "args": [
              '--remote-debugging-port=9222'
          ],
          "defaultViewport": {
            "height": 1080,
            "width": 1920
          },
          "headless": false
        });

    // 2. Open a new page
    const page = await browser.newPage();

    // 3. Navigate to URL
    await page.goto('https://');

    await new Promise(r => setTimeout(r, 10000));
    console.log('Ready');

    var contactList = ['cesar','gab','777','81411579','34353'];
    var fLen = contactList.length;
    var j = 0;

    for (i = 0; i < fLen; i++) {

        await page.evaluate(() => {

            function searchContact(contact_name = "") {
                //search = document.querySelector('#side > div._1Ra05 > div > label > div > div._1awRl.copyable-text.selectable-text');
                search = document.querySelector('#side > div._1Ra05 > div > label > div > div._1awRl.copyable-text.selectable-text');
            }
            j++;
            searchContact(contactList[j]);

        }
    }
1 Answers

Take a a look at the Puppeteer documentation for page.evaluate(pageFunction[,...args]). It states:

pageFunction <function|string> Function to be evaluated in the page context

Note (my bold) "evaluated in the page context". The variables j and contactList do not exist in the context of the page.

Thankfully however, Puppeteer has a way of calling server side code from the context of the page with page.exposeFunction(name, puppeteerFunction)

The method adds a function called name on the page's window object. When called, the function executes puppeteerFunction in node.js and returns a Promise which resolves to the return value of puppeteerFunction.

For your use case, it would look something like the following:

const puppeteer = require('puppeteer');

(async function()
{
    const browser = await puppeteer.launch({
        headless: false,
        args: [
            "--no-sandbox", // I needed these args for it to run on my machine, you probably don't need them.
            "--disable-setuid-sandbox"
        ]
    });
    const page = await browser.newPage();
    const contacts = ["Charlie", "Carl", "Dennis", "Conrad"];
    await page.exposeFunction("getContacts", function()
    {
        return contacts;
    });
    await page.exposeFunction("addContact", function(contact)
    {
        contacts.push(contact);
    });
    await page.evaluate(async function()
    {
        await addContact("Henry");
        await addContact("Olav");
        const contacts = await getContacts();
        contacts.forEach(function(contact)
        {
            const div = document.createElement("div");
            div.innerHTML = contact;
            document.body.appendChild(div);
        });
    });
    console.log("Contacts after evaluating page function: ", contacts.join(", "));
})()

Note that this is a toy example, although a complete and runable one. You should be able to figure out the rest from this. The code you posted in your example in the OP does not make much sense (i.e. the endlessly recursive function searchContact()) so you will just have to adapt this to your use case.

Related