๊ทํ์ ํ๊ฒฝ์ ๋ํด ์๋ ค์ฃผ์ญ์์ค.
๋ฌธ์ ๋ฅผ ์ฌํํ๋ ๋จ๊ณ๋ ๋ฌด์์ ๋๊น?
const puppeteer = require('puppeteer');
const run = async () => {
const browser = await puppeteer.launch();
// close any open pages
let pages = await browser.pages();
await Promise.all(pages.map(async page => await page.close()));
// handle a page being closed
browser.on('targetdestroyed', async target => {
const openPages = await browser.pages();
console.log('Open pages:', openPages.length);
if (openPages.length == 0) {
console.log('Closing empty browser');
await browser.close();
console.log('Browser closed');
}
});
pages = await browser.pages();
for (let i = 0; i < 5; i++) {
await browser.newPage();
}
pages = await browser.pages();
pages.forEach((page) => page.close());
};
run();
์์๋๋ ๊ฒฐ๊ณผ๋ ๋ฌด์์ ๋๊น?
Count: 0
Open pages: 4
Open pages: 3
Open pages: 2
Open pages: 1
Open pages: 0
Closing empty browser
Browser closed
๋์ ์ด๋ป๊ฒ ๋๋์?
Open pages: 4
Open pages: 3
Open pages: 2
Open pages: 1
Open pages: 0
Closing empty browser
(node:29074) UnhandledPromiseRejectionWarning: Error: Protocol error (Target.closeTarget): Target closed.
at Promise (node_modules/puppeteer/lib/Connection.js:86:56)
at new Promise (<anonymous>)
at Connection.send (node_modules/puppeteer/lib/Connection.js:85:12)
at Page.close (node_modules/puppeteer/lib/Page.js:802:36)
at pages.forEach (test.js:27:32)
at Array.forEach (<anonymous>)
at run (test.js:27:9)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
(node:29074) 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(). (rejection id: 1)
(node:29074) [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.
Browser closed
์ด๊ฒ์ ๋งค๋ฒ ์คํ๋๋ ๊ฒ์ ์๋์ง๋ง ๋งค๋ฒ ์์ฃผ ๋ฐ์ํฉ๋๋ค. ๋ด๊ฐ ์ฌ๊ธฐ์ ๋ญ๊ฐ _bad_ํ๊ณ ์๋ ๊ฒ์ด ์ ์ ์ผ๋ก ๊ฐ๋ฅํ๋ค!
+1
์ฝ๊ฐ์ ๋น ๋ฅธ ๋๋ฒ๊น
์ ์ํํ๋ฉด targetDestroyed
page.close()
๋ฉ์์ง๊ฐ ํ์ธ๋๊ธฐ ์ ์ targetDestroyed
์ด๋ฒคํธ๊ฐ ๋ฐ์ํฉ๋๋ค (๋๋ ์ธํ์ด ํ์ธ์ ์ฒ๋ฆฌํ์ต๋๋ค).
๋๋ ๊ทธ๊ฒ์ ๊ณ ์น๋ ๋ฐฉ๋ฒ์ ์๊ฐํ ์์๋ค-์๋ฅผ ๋ค๋ฉด targetDestroyed
์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ ์ Target.closeTarget
์น์ธ์ ๊ธฐ๋ค๋ฆฐ๋ค. ๊ทธ๋๋ ์ฌ๋ฐ๋ฅด๊ฒ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋ ๋ค๋ฅธ ์ง๋ฌธ์
๋๋ค!
์กฐ์ฌ์ ๋ํด @MJPA ์๊ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค.
์ด ๋ฌธ์ ๋ ๊ด๋ จ ํ์ด์ง๊ฐ ๋ซํ๊ธฐ ์ ์ browser
์ด ๋ชฉ๋ก์์ ๋์์ ์ ๊ฑฐํ๋ค๋ ์ฌ์ค์์ ๋น๋กฏ๋ฉ๋๋ค.
๋ค์ ์์์๋ page.close()
ํธ์ถ์ด ์๋ฃ ๋ ๋๊น์ง browser.pages()
๊ฐ 1 ํ์ด์ง๋ฅผ๋ณด๊ณ ํ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const [page] = await browser.pages();
browser.on('targetdestroyed', async () => console.log('Target destroyed. Pages count: ' + (await browser.pages()).length));
console.log('closing page...');
await page.close();
console.log('page closed.');
await browser.close();
})();
์ถ๋ ฅ :
closing page...
Target destroyed. Pages count: 0
page closed.
@JoelEinbinder ์ด๋ป๊ฒ ์๊ฐํ์ธ์?
@MJPA ์ ๋์ผํ ๋ฌธ์
await page.waitForSelector('aside.aside a[href="/checkout"]')
.then(() => {
logMessage('Checkout is available');
})
.catch(err => {
log('Checkout not available');
success = false;
browser.close();
});
// click checkout button
await Promise.all([
page.click('aside.aside a[href="/checkout"]'),
page.waitForNavigation()
]);
์ด ๊ฒฝ์ฐ ํญ์ ๋์ผํ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.
์ด ์ธํ๊ทน ์ค๋ฅ ์ผ ์๋ ์์ต๋๋ค.
์ฝ๊ฐ ์ ์ฌํ ๊ตฌํ์ผ๋ก ๋์ผํ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง๋ง page
์์ close
์ด๋ฒคํธ๋ฅผ ์์ ํ๋ฉด๋ฉ๋๋ค. ๋ฌธ์๋ "๋ซ๊ธฐ"์ ์๋ฏธ์ ๋ํด ์ง๋์น๊ฒ ๋ช
์ ์ ์ด ์ง ์์ง๋ง ๊ตฌํ์ ๋ฐ๋ผ ํ์ด์ง๊ฐ ๋ซํ๊ธฐ ์ ์ close
๊ฐ ์คํ๋๋ฏ๋ก ๋ค์ ์์ ๋ targetdestroyed
์ ์ ์ฌํ๊ฒ ์๋ํ์ง ์์ต๋๋ค.
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
// create 5 test pages
for(let i=0; i<5; i++){
let page = await browser.newPage();
// listen to page close event and close browser
// when all get closed
page.on('close', async () => {
let pages = await browser.pages();
if(!pages.length){
// will not get here!
browser.close();
}
});
}
let pages = await browser.pages();
pages.forEach(async (page) => await page.close());
์ด๋ฒคํธ๊ฐ closed
์๋๋ผ close
๋ผ๊ณ ๋ถ๋ฆฌ๊ธฐ ๋๋ฌธ์์ด _sort of_๊ฐ ์๋ฏธ๊ฐ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. close()
promise ์ฝ๋ฐฑ์์ ๋ด ์์ ์ closed
์ด๋ฒคํธ๋ฅผ ์์ฑํ๊ณ ๋์ ์์ ํ์ฌ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ต๋๋ค.
page.close().then(() => {
page.emit('closed');
});
์ด์ผ๊ธฐ์ ๊ตํ์ ๋ธ๋ผ์ฐ์ ๊ฐ ์ธ์ ๋ซํ๋ ์์ ํ์ง (์์ธ๋ฅผ ํฌ์ฐฉํ์ง ์๊ณ ) ์ ์์๋ 100 % ๋ณด์ฅ ๋ ๋ฐฉ๋ฒ์ด ์๋ค๋ ๊ฒ์ ๋๋ค. ๋ด๊ฐ ๋น ์ง ๊ฒ์ด ์์ผ๋ฉด ์๋ ค์ฃผ์ธ์.
# 3423๊ณผ ๊ด๋ จ์ด์์ ์ ์์ต๋๊น?
๋ธ๋ผ์ฐ์ ์ ๋ชจ๋ ํญ์ ๋ซ์ ๋ค์ ์ ํ์ด์ง๋ฅผ ์ด๋ ค๊ณ ํ๋ฉด์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
๋ค์ ์์์๋
page.close()
ํธ์ถ์ด ์๋ฃ ๋ ๋๊น์งbrowser.pages()
์์ 1 ํ์ด์ง๋ฅผ๋ณด๊ณ ํ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค.
์์ ์์์ ์ฝ๋๊ฐ ์์๋ฉ๋๋ค. ๋ง์ง๋ง์ผ๋ก ๋ซํ ํ์ด์ง, brower.pages (). length๋ 1์ด๊ณ ๋ธ๋ผ์ฐ์ ๋ ๋ซํ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ฉด ๋ ์ด์ ํ๊ฒ ํ๊ดด ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ง ์๊ณ ๋ธ๋ผ์ฐ์ ๋ ์์ํ ์ด ๊ฒ์ ๋๋ค.
๋ฏธ๋ฌํ์ง๋ง ์ด๊ฒ์ด ์ฌ์ฉ์ ์ค๋ฅ๋ผ๊ณ ๋งํ๊ณ ์ถ์ต๋๋ค. ๋ฅผ ํธ์ถํ๊ธฐ page.close
ํธ์ถํ๊ธฐ ์ ์ ๊ธฐ๋ค๋ ค์จํด์ผ browser.close()
.
์ฌ์ฉ์ ์ ์ด ํ์ด์ง๊ฐ ์์ผ๋ฉด Promise.all ๋ชจ๋ ํ์ด์ง๊ฐ ๋ซํ๊ณ ๋ธ๋ผ์ฐ์ ๋ฅผ ๋ซ์ต๋๋ค. targetdestroyed
์ด๋ฒคํธ๋ฅผ ์์ ํ ํ์๊ฐ ์์ต๋๋ค. ๋๋ browser.close๋ฅผ ํธ์ถํ๊ณ ๋ชจ๋ ํ์ด์ง๋ฅผ ์๋์ผ๋ก ๋ซ์ต๋๋ค.
์ฌ์ฉ์ ์ ์ด ํ์ด์ง๊ฐ์๋ ๊ฒฝ์ฐ targetdestroyed
์ด๋ฒคํธ๋ฅผ ์์ ํ์ง๋ง page.close
๋ฅผ ํธ์ถ ํ ํ์๋ ์์ต๋๋ค.
+1.
page.on("popup")
ํ์
์ ๋ซ์ ํ์ด ์ค๋ฅ๊ฐ ํ์๋๊ธฐ ์์ํ์ต๋๋ค. ํ๋ ์ ์ปจํ
์คํธ ๋ด์์ ํ์
์ด ๋ฐ์ํ๋ฉด "popup.close ()"๋ก ํ์
์ ๋ซ์ ์์๊ณ ํผ ํผํฐ๊ฐ ํญ์ ์ด์ด๋๊ธฐ ๋๋ฌธ์ ์ ์ฒด ๋ธ๋ผ์ฐ์ ๋ฅผ ๋ซ์ผ๋ ค๊ณ ํ๋ฉด "Target Closed"์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ์คํฌ๋ฆฝํธ๊ฐ ์ค์ง๋ฉ๋๋ค.
Chrome 73๊ณผ ํจ๊ป puppeteer 1.14๋ฅผ ์ฌ์ฉํฉ๋๋ค (Chromium์ ์ฌ์ฉํ์ง ์์).
๋ธ๋ผ์ฐ์ ๋ฅผ ๋ซ๋ ๋ฐ ์ฌ์ฉํ๋ ์ฝ๋
async close_browser() {
for (let page of await this.browser.pages()) {
await page.close({
"runBeforeUnload": true
});
}
await this.browser.close();
}