puppeteer : how check if browser is still open and working
Asked Answered
S

3

21

im trying to open multiple tabs in a single browser instance , after they're done i close the tabs and then re-opening those tabs every x seconds ... but i want to keep the browser itself open so i dont have to login in each tab on every loop

so the browser remains open , tabs open and close

here is my simplified code , pleas ignore syntax erros

var  global_browser = false ;
async function init_puppeteer( settings ) {



    if(global_browser === false )
        global_browser = await puppeteer.launch({headless: false  , args:['--no-sandbox']});

    for(var i = 0  ; i < settings.length ; i++ )
    {
        var setting = settings[i];
        open_tab($setting);
    }
}



 async function open_tab( setting ){
    const page    = await global_browser.newPage();
    // do stuff 
    page.close();   
}

setInterval(function (){
    init_puppeteer(settings)
}, 50000 );

here is the problem , sometimes browser crashes or it get closed for whatever reason but the global_browser remains an object /instance of puppeteer ... of curse it wont work when i try open a tab with that instance , and i get something like

(node:5720) UnhandledPromiseRejectionWarning: Error: WebSocket is not open: readyState 3 (CLOSED)

here is my question , how can i check and make sure i have a working/open instance of puppeteer in global_browser ? so i can create a new instance and replace it if the previous one is closed

Selfforgetful answered 27/8, 2018 at 19:9 Comment(3)
You are calling page.close(); in your open_tab() function. I think that's why it closes the browser.Aby
He is asking how to tell if it is closed or not. Not why it closes.Glairy
Related GH issue #3149Pubes
P
45

Use browser.on('disconnected').

You can use browser.on('disconnected') to listen for when the browser is closed or crashed, or if the browser.disconnect() method was called.

Then, you can automatically relaunch the browser, and continue with your program.

The following class will launch the browser, and automatically relaunch the browser whenever the 'disconnected' event is fired:

class BrowserHandler {
  constructor() {
    const launch_browser = async () => {
      this.browser = false;
      this.browser = await puppeteer.launch();
      this.browser.on('disconnected', launch_browser);
    };
    
    (async () => {
      await launch_browser();
    })();
  }
}

BrowserHandler.browser will return false when disconnected.

Additionally, the following function will give you the ability to force your program to wait for the browser to finish launching before continuing any further:

const wait_for_browser = browser_handler => new Promise((resolve, reject) => {
  const browser_check = setInterval(() => {
    if (browser_handler.browser !== false) {
      clearInterval(browser_check);
      resolve(true);
    }
  }, 100);
});

Complete Example:

'use strict';

const puppeteer = require('puppeteer');

/**
 * Class: BrowserHandler
 *     Relaunch Browser when Closed
 *     Return false when Browser is Disconnected
 */

class BrowserHandler {
  constructor() {
    const launch_browser = async () => {
      this.browser = false;
      this.browser = await puppeteer.launch();
      this.browser.on('disconnected', launch_browser);
    };
    
    (async () => {
      await launch_browser();
    })();
  }
}

/**
 * Function: wait_for_browser
 *     Wait for Browser to Finish Launching
 */

const wait_for_browser = browser_handler => new Promise((resolve, reject) => {
  const browser_check = setInterval(() => {
    if (browser_handler.browser !== false) {
      clearInterval(browser_check);
      resolve(true);
    }
  }, 100 );
});

// Main Program

(async () => {
  // Open Browser
  
  const browser_handler = new BrowserHandler;
  
  await wait_for_browser(browser_handler);
  
  // Open New Page
  
  let page = await browser_handler.browser.newPage();
  
  await page.goto('https://www.example.com/');
  
  // Disconnect and Automatically Reconnect Browser
  
  browser_handler.browser.disconnect();
  
  if (browser_handler.browser === false) {
    console.log('The browser has been disconnected.');
    
    await wait_for_browser(browser_handler);
  }
  
  console.log('The browser has been reconnected.');
  
  // Close and Automatically Reopen Browser
  
  await browser_handler.browser.close();
  
  if (browser_handler.browser === false) {
    console.log('The browser has been closed.');
    
    await wait_for_browser(browser_handler);
  }
  
  console.log('The browser has been reopened.');
  
  // Force Close Puppeteer
  
  process.exit();
})();

Result:

The browser has been disconnected.

The browser has been reconnected.

The browser has been closed.

The browser has been reopened.

Pulling answered 30/8, 2018 at 21:8 Comment(2)
As for this moment, for me, this solution not working, Only restart the application works.Stemson
Grant, can you explain how to extend this so it also reopens the "page" when the page closed? So, if the page closes, it reopens. If the browser closes, it reopens the browser AND the page.Creatural
G
8

If you just close all tabs (or browser window) but browser process is still there (but no any window).

disconnected event will not be triggered.

Then you can check whether all tabs are closed by:

        if ((await browser.pages()).length === 0) {
          // no tabs opening, do stuff
        }
Goodoh answered 3/6, 2020 at 2:26 Comment(0)
G
2

You can make a very simple function to know if the browser process was killed.

async function wasBrowserKilled(browser){
  const procInfo = await browser.process();
  return !!procInfo.signalCode; // null if browser is still running
}

We can use this here,

const browserKilled = await wasBrowserKilled(global_browser);
if(global_browser === false || browserKilled)

It will check if the browser was killed, otherwise it will replace it.

This is just one way out of many provided by the API.

This is the code I used to test this out, see how the output changes if I comment out the browser.close() section.

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  // comment out to keep browser open
  await browser.close();
  console.log({browserKilled: await wasBrowserKilled(browser)});
});

async function wasBrowserKilled(browser){
  const procInfo = await browser.process();
  return !!procInfo.signalCode;
}

Log here,

➜  puppeteer-xvfb git:(direct-script) ✗ node temp/interval_tab.js
{ browserKilled: true }
➜  puppeteer-xvfb git:(direct-script) ✗ node temp/interval_tab.js
{ browserKilled: false }
_

This is different than the event. I made this snippet specially to check the process for this specific question where you check and run it if you want.

Note that this will only produce result if the browser is crashed/closed somehow.

Glairy answered 30/8, 2018 at 10:54 Comment(2)
thanx but procInfo.signalCode is null both for open and closed browserSelfforgetful
My end showed SIGKILL for signalCode :/ Show me how you are closing the browser/check when it crashes.Glairy

© 2022 - 2024 — McMap. All rights reserved.