Jack Ernst
Jack Ernst

Reputation: 13

Intergrate puppeteer tasks into one single task

I created several javascript files which looks like this:

const somedata = ""
const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch();
  const pages = await browser.pages();
  const page = pages[0];
  await page.goto('https://somewebsite.com');

  ///Do some task

  browser.close();
})();

I managed to perform single operation using each individual file . Now, I want to create only one browser instance and do task specified in those individual files. I want pass some data in each of the task. Also at a time only five pages should be remain open.

I'm using puppeteer and NodeJS.

Upvotes: 1

Views: 1035

Answers (1)

Baboo
Baboo

Reputation: 4258

You can create a BrowserService that is a singleton and encapsulate the page creation and deletion:

// BrowserService.ts
export class BrowserService {
    public static instance: BrowserService | null = null;

    public static async getInstance(): Promise<BrowserService> {
        if (this.instance == null) {
            this.instance = new BrowserService();
            await this.instance.initialise();
        }

        return this.instance;
    }

    private browser: PuppeteerBrowser;

    private numberPages: number = 0;

    private constructor() { }

    /**
     * Get a browser page.
     */
    public async getPage(): Promise<PuppeteerPage> {
        // Handle the logic of page creation and limit the number of created pages.

        // ...
        const page = (await this.browser.pages())[0];
        // ...

        return page;
    }

    /**
     * Close a page.
     */
    public async closePage(page: PuppeteerPage): Promise<void> {
        // Handle the logic of page deletion and browser closing.

        // ...
        if(this.numberPages === 0) {
            await this.browser.close();
            BrowserService.instance = null;
        }
        // ...
    }

    /**
     * Initialise the instance.
     */
    public async initialise(): Promise<void> {
        this.browser = puppeteer.launch();
    }
}

And use it in your code:

// myPuppeteerTask.ts
const somedata = ""
const puppeteer = require('puppeteer');
(async () => {
    const browserService: BrowserService = await BrowserService.getInstance();
    const page = await browserService.getPage();
    await page.goto('https://somewebsite.com');

    ///Do some task

    browserService.closePage(page);
})();

The BrowserService is a singleton created by hand but you can improve this architecture using dependency injection using NestJs or Awilix for example. You get better maintanability, readalbility and testability.

It would look like this:

// myPuppeteerTask.ts
export class MyPuppeteerTask {

    // Inject the BrowserService into the task.
    public constructor(private browserService: BrowserService) { }

    public async execTask(): Promise<void> {
        const page = await this.browserService.getPage();
        await page.goto('https://somewebsite.com');

        ///Do some task

        this.browserService.closePage(page);
    }
}

Upvotes: 1

Related Questions