admin管理员组

文章数量:1384263

I am using the exposeFunction-mand in the following manner:

await this.page.exposeFunction('foo', function(){ return 'bar'; });

This works as intended and gives me the window.foo-function.

If I call this code again, I get the following error:

Error: Failed to add page binding with name foo: window['foo'] already exists!

This error even persists when navigating with page.goto().

Is there a way to unbind a function exposed by exposeFunction()?

I am using the exposeFunction-mand in the following manner:

await this.page.exposeFunction('foo', function(){ return 'bar'; });

This works as intended and gives me the window.foo-function.

If I call this code again, I get the following error:

Error: Failed to add page binding with name foo: window['foo'] already exists!

This error even persists when navigating with page.goto().

Is there a way to unbind a function exposed by exposeFunction()?

Share Improve this question edited Nov 20, 2020 at 12:45 hardkoded 21.8k3 gold badges61 silver badges74 bronze badges asked Dec 2, 2019 at 11:16 sarahlisasarahlisa 1315 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 6 You could change the function stored in the `_pageBindings` map. This is quite hacky because you would change an internal variable, but it's the only way to solve this.
await this.page.exposeFunction('foo', function(){ return 'bar'; }); 
this.page._pageBindings.set('foo', function(){ return 'baz'; });

UPDATE April-2024
Puppeteer 20.6 introduced removeExposedFunction. You can do this:

await this.page.exposeFunction('foo', function(){ return 'bar'; }); 
await this.page.removeExposedFunction('foo'); 

You might not need to remove the function and simply try/catch it as described here, but there's no way to make a remendation without more context.

Nonetheless, a general approach is to add another layer of indirection: instead of putting your Node logic directly in the exposed function, use the exposed function as a wrapper on the real thing, passing args along.

This way, instead of removing the function, you can simply disable or replace it at your whim, since all of the code will be running under Node control. For example:

const puppeteer = require("puppeteer"); // ^22.6.0

let browser;
(async () => {
  const url = "https://www.example./";
  browser = await puppeteer.launch();
  const [page] = await browser.pages();

  let fn = (...args) => {
    console.log("fn called with args:", args);
  };

  await page.exposeFunction("fn", (...args) => {
    fn(...args);
  });

  await page.goto(url, {waitUntil: "domcontentloaded"});
  await page.evaluate('fn("hello")');

  // disable fn:
  fn = () => {
    throw Error("fn is disabled");
  };

  // or, if you want, make it a no-op rather than a throw:
  // fn = () => {};

  // or make it do something else:
  // fn = (...args) => {
  //  console.log("Changed! fn called with args:", args);
  // };

  try {
    await page.evaluate('fn("hello")');
  } catch (err) {
    console.error(err.message); // => fn is disabled
  }
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close());

A more typical use case is to replace the function with a different implementation. The above code works fine for that as well. See this answer for a real-world example.

You can also use the first argument of your exposed function to determine which Node function to call, which might be useful for certain situations. You technically only need to expose one function, which can forward the call wherever it needs to go in Node.

Consider also arranging your control flow such that exposeFunction isn't invoked more than once, ideally right after the page is created. This would be use-case specific.

Closing and recreating the page is another option to consider.

You could use try and catch. So if the function is exposed it will throw an error and be caught. Something like this:

try {
   await page.exposeFunction('yourfunction', () => {return 'somethin'})
} catch (err)  {
   // the error will be caught, so no worries
}

本文标签: javascriptPuppeteerRemove function exposed by exposeFunctionStack Overflow