Waqar Haider
Waqar Haider

Reputation: 971

Puppeteer response not returning css file

I am trying to return the full css response and save to the file but it is returning some weird object: here is my code:

const puppeteer = require('puppeteer'),
    fs = require('fs');
const JSON = require('circular-json');

function run (url) {
    return new Promise(async (resolve, reject) => {
        try {
            const browser = await puppeteer.launch();
            const page = await browser.newPage();

            var allCSS = [];
            let css = await page.on('response', async response => {
                if(response.request().resourceType() === 'stylesheet') {
                    return JSON.stringify(response.text());
                }
            });
           let body = await page.evaluate(() => {
               return items = document.getElementsByTagName('#Id');
           })

            await page.goto(url);
            await browser.close();
            return resolve({body: body, css: css});
        } catch (e) {
            return reject(e);
        }
    })
}
run("http://localhost/gogo/test.html")
    .then((css)=>{
        //var css = JSON.stringify(body.css);
        fs.writeFile('data/css/first.css', css, 'utf8', function(){
            console.log("CSS DONE")
        });
    }).catch(console.error);

Now the issue is that it is returning an object with all the stuff with like events..., _connection... and its a huge json file now? how do i get only the stylesheet

Upvotes: 0

Views: 1722

Answers (2)

Nathan
Nathan

Reputation: 7855

Have you considered something like this?

  const promise = new Promise(async (resolve, reject) => {
    const css = [];

    page.on('response', async response => {
      if (response.request().resourceType() === 'stylesheet') {
        css.push(await response.text());
      }
    });

    page.on('load', () => resolve(css)); // Ensure the page is loaded before resolving
  });

And then just check your promise:

  (async () => {
    const result = await promise;

    console.log(result);
  })();

This approach differs from yours in that you can continue to stay in the page/session without closing the browser. This might be helpful in cases where you may want to perform additional checks on the page.

Upvotes: 0

The Guy with The Hat
The Guy with The Hat

Reputation: 11132

response.text() returns a Promise, not the actual text itself. You would need to await the result of this promise, something like this:

return JSON.stringify(await response.text());

However, I believe that there's another issue. As far as I am aware, you cannot await an event; you can only create the callback for an event. So, this code is inherently incorrect:

let css = await page.on(...

Fixing this should not be too difficult. What you need to do is register the event callback similar to how you have been doing so:

page.on('response', async response => {
    if(response.request().resourceType() === 'stylesheet') {

But then, inside the callback, you should resolve the promise:

        resolve(JSON.stringify(await response.text()));

Alternately, if you want to capture more than one stylesheet, you'd need to add the CSS to your list. Then, after you reach a certain threshold (time, number of stylesheets captured, etc.), you resolve the promise with that list of all the CSS.

Final code (for only one stylesheet) should look something like this:

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

    page.on('response', async response => { // don't await anything on this line
        if(response.request().resourceType() === 'stylesheet') {
            resolve(JSON.stringify(await response.text())); // await and resolve here
        }
    });

    await page.goto(url);
    await browser.close();
    // don't resolve here
} catch (e) {
    return reject(e);
}

Upvotes: 1

Related Questions