How do I call function outside async function in puppeteer with nodeJS

Viewed 2241

how do I call a function passing the page object outside async method in puppeteer.

I want to implement a functionality where if a certain value is found on page it should play a music. I have defined playmusic() functionality outside async method .

const puppeteer = require('puppeteer');

const playmusic = ()=>{
   page.goto('http://www.noiseaddicts.com/free-samples-mp3/?id=2544');
   page.click('span.map_play');
}

(async () => {
  const browser = await puppeteer.launch({headless : false});
  
  const page = await browser.newPage();

 
  await page.goto('DesiredURL');
  const pricing = await page.evaluate(()=>{
    let pricesOnPage=document.querySelectorAll(".span_price_wrap");
    const priceList=[...pricesOnPage];
    return priceList.map(h=>h.innerText);
    
  });
  console.log(pricing[1]);

  if(pricing[1]>=2316)
  {
    await page.evaluate(() => {
      playmusic ();
    });
  }

 await browser.close();
})();

I m getting below error

\index.js
2346.75
(node:17316) UnhandledPromiseRejectionWarning: Error: Evaluation failed: ReferenceError: playmusic is not defined
    at __puppeteer_evaluation_script__:2:6
    at ExecutionContext._evaluateInternal (\jswebscrapping\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:217:19)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async ExecutionContext.evaluate (\jswebscrapping\node_modules\puppeteer\lib\cjs\puppeteer\common\ExecutionContext.js:106:16)
    at async index.js:24:4
(node:17316) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:17316) [DEP0018] 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.

------------------------------UPDATE--------------------------------------------

Sharing the workable code: Thanks everyone for helping I have improved my code in couple of places such as

  1. added wait time before and after playing the music .
  2. Converted return value in float ( earlier it was treated as string )
const puppeteer = require('puppeteer');

 const playmusic = async (page)=>{
  await page.goto('http://www.noiseaddicts.com/free-samples-mp3/?id=2544');
  await page.waitFor(4000) ;
  await page.click('span.map_play');
  await page.waitFor(12000);
}

(async () => {
  const browser = await puppeteer.launch({headless : false});
  
  const page = await browser.newPage();

 
  await page.goto('MYURL');
  const pricing = await page.evaluate(()=>{
    let pricesOnPage=document.querySelectorAll(".span_price_wrap");
    const priceList=[...pricesOnPage];
    return priceList.map(h=>h.innerText);
    

  });
  console.log(pricing[1]);
  let PricingFloat= parseFloat(pricing[1]);

  if(PricingFloat<=21)
  {
    await playmusic (page);   
  }
  else
  {
    console.log("No Music for you");
  }

 await browser.close();
})();
1 Answers

You need to replace

const playmusic = ()=>{
   page.goto('http://www.noiseaddicts.com/free-samples-mp3/?id=2544');
   page.click('span.map_play');
}

by

const playmusic = (page) => {
   page.goto('http://www.noiseaddicts.com/free-samples-mp3/?id=2544');
   page.click('span.map_play');
}

and

    await page.evaluate(() => {
      playmusic ();
    });

by

    await page.evaluate(() => {
      playmusic (page);
    });

Because of range when page exists is constrained and when you define function playmusic then this function do not have access to variable page. You can read more about variables scopes in JS.

Link to a great article:

https://www.sitepoint.com/demystifying-javascript-variable-scope-hoisting/


UPDATE

After analyzing your code of error I think you need to add a try-catch block. For example.

try {
    await page.evaluate(() => {
      playmusic (page);
    });
} catch(e) {
   console.log(e);
   process.exit(1)
}

You should also check if the puppeteer does not have unrejected promised:

https://pptr.dev/#?product=Puppeteer&version=v5.3.0&show=api-class-page

For example, you can write:

const playmusic = async (page) => {
   await page.goto('http://www.noiseaddicts.com/free-samples-mp3/?id=2544');
   return page.click('span.map_play');
}

and in your main code:

try {
    await page.evaluate(async () => {
      try {
         await playmusic();
      } catch(e) {
          console.log(e);
          process.exit(1);
      }
    });
} catch(e) {
   console.log(e);
   process.exit(1)
}
Related