Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closing Tabs after printToPdf #214

Closed
gnat42 opened this issue Jul 25, 2017 · 4 comments
Closed

Closing Tabs after printToPdf #214

gnat42 opened this issue Jul 25, 2017 · 4 comments
Labels

Comments

@gnat42
Copy link

gnat42 commented Jul 25, 2017

Apologies, I've nearly got this working but can't seem to figure out how to close a tab that was opened.

Component Version
Operating system CentOS7
Node.js 8.2.1
Chrome 60.0.3112.66
chrome-remote-interface 0.24.2

Everything seems to work except for one part which is closing the tabs I've opened. I expose this code via https get/post requests. For each request I open a new tab and either fetch the html or load the html directly. Once loaded, output a pdf and return the filename they can request to get the printed pdf (or directly return it). This works pretty good. Using ab I can do many concurrent requests and everything seems to work. There is one small issue is that it doesn't seem to close the tab. Since I'm running headless I'm seeing a new process for each request open. For example, when I first start Chrome, I have a total of 5 processes. For every request I make, I get another chrome process. It doesn't seem to go away. I'm fairly certain its because I'm calling client.close(); but not closing the tab first. You can see in the function getPdf included below that I've commented where I think I should be closing the tab but have so far been unable to do so. Full project source is here

async function load(html) {
    console.log('Load(html) called');

    const tab = await CDP.New({port: options.port});
    const client = await CDP({tab});
    const {Network, Page} = client;
    await Promise.all([Network.enable(), Page.enable()]);

    return new Promise((resolve, reject) => {
        let failed = false;

        Network.loadingFailed(() => {
            failed = true;
            console.log('Load(html) Network.loadingFailed');
            reject(new Error('Load(html) unable to load remote URL: ' + html));
        });

        const url = /^(https?|file|data):/i.test(html) ? html : `data:text/html,${html}`;
        Page.navigate({url});
        Page.loadEventFired(() => {
            if (!failed) {
                console.log('Load(html) resolved');
                resolve({client: client, tab: tab});
            }
        });
    });
}

async function getPdf(html) {
    const {client, tab} = await load(html);
    const {Page} = client;

    console.log("tabID: "+tab.id);
    // https://chromedevtools.github.io/debugger-protocol-viewer/tot/Page/#method-printToPDF
    const pdf = await Page.printToPDF(options.printOptions);

    // how do I close the tab here???
    client.close();

    return pdf;
}
@hbakhtiyor
Copy link
Contributor

you can use CDP.Close method

e.g.

async function getPdf(html) {
    const {client, tab} = await load(html);
    const {Page} = client;

    console.log("tabID: "+tab.id);
    // https://chromedevtools.github.io/debugger-protocol-viewer/tot/Page/#method-printToPDF
    const pdf = await Page.printToPDF(options.printOptions);

    await CDP.Close({port: options.port, id: tab.id}); // here's you need to pass tab id

    return pdf;
}

@cyrus-and
Copy link
Owner

@gnat42 yes you can do as @hbakhtiyor says (thanks!); as you can see there should be no need to also close the client.

Just make sure to proper handle errors in your code so you don't leave dangling tabs around.

@gnat42
Copy link
Author

gnat42 commented Jul 25, 2017

Ah, that's how it works, I had tried CDP.Close({tab.id}); client.target.closeTarget() and a variety of others. This works perfectly. @hbakhtiyor Much appreciated!

One question @cyrus-and being quite new to Node/JS and this api. I don't really know all the places/errors I could experience. I'm thinking that I need to close the tab in

Page.loadEventFired(() => {
            if (!failed) {
                console.log('Load(html) resolved');
                resolve({client: client, tab: tab});
                return;
            }
            CDP.Close({port: options.port,id: tab.id});
        });

Are there other places in that code that you see have potential for errors I'm not catching? If so are there docs someplace that detail what exceptions/errors a function can throw?

@cyrus-and
Copy link
Owner

@gnat42 every method that returns a Promise could in principle fail, if you use the async/await pattern this means that each await f(); could throw an exception. Make sure to properly use try/catch/finally to handle your errors and perform cleanup code. For example:

try {
    await f();
} catch (err) {
    // notify the user
} finally {
    // cleanup code
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants