Вы можете создать BrowserService
, который является одноэлементным и инкапсулировать создание и удаление страницы:
// 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();
}
}
И использовать его в своем коде:
// 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);
})();
BrowserService
- это синглтон, созданный вручную, но вы можете улучшить эту архитектуру, используя внедрение зависимостей, например, с помощью Nest Js или Awilix. Вы получаете лучшую поддержку, удобочитаемость и тестируемость.
Это будет выглядеть так:
// 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);
}
}