Is there a way to determine if a Puppeteer Page is currently in a loading state?

In my coding project involving Puppeteer, I have designed a generic "click" function and a "getHtml" function as part of a wrapper:

class Page {
    
        ....

    async click(selector: string) {

        await this.context.evaluate((querySelector, text) => {

            const elem = document.querySelector(querySelector) as HTMLInputElement;

            if (elem) {

                elem.click();
            }

        }, selector);
    }

    async getHtml() {//

        const html = await this.context.evaluate(() => {
            return document.querySelector('html')?.innerHTML;
        })

        return html;
    }
}

As observed, the click() method simply takes a querySelector and clicks on the located element.

However, there is an issue that arises when the element clicked initiates a navigation event, leading to subsequent functions encountering the following error:

Execution context was destroyed, most likely because of a navigation

For instance, if the user code contains commands like:

const page = new Page(...)
...

await page.click('someSelector')//If this selector points to a link, it triggers a navigation.

await page.getHtml()//This command then results in an error

Is there any way to determine if a navigation event is pending so that I could optionally wait for it within different functions?

Simply implementing waitForNavigation by default inside the click function is not viable, as it will cause the program to freeze if the click does not lead to navigation.

Answer №1

Two Years Later...

I found myself in this situation after encountering the error message

Execution context was destroyed [...]
following the use of page.goto() and page.content().

Summary

// workaround to prevent 'page.waitForNavigation()' from blocking
await page.waitForSelector('html')

The method page.waitForSelector('html') would resolve immediately without any redirections caused by changes in location.href or History.pushState(), and only wait for one redirect upon successful navigation.

- Why Does This Occur?

In my scenario, the issue stemmed from modifying the location.href after the page had loaded. Consequently, content was being requested while the page was transitioning to a new URL.

- Why Not Use page.waitForNavigation()?

page.waitForNavigation() inevitably pauses until a navigation is completed. Similar to the original poster (OP), I couldn't guarantee that a navigation would always occur, nor could I predict the timing. Therefore, I chose to avoid unnecessary delays by opting not to utilize this method.

- Limitations

If the server returns anything other than a valid HTML response, page.waitForSelector('html') will block and eventually timeout, resulting in an error.

Answer №2

Perhaps implementing a solution similar to the following could be beneficial?

const [_, navigation] = await Promise.allSettled([
  elem.click(),
  page.waitForNavigation(),
]);

if (navigation.status === 'fulfilled') /* Indicates successful navigation. */;
else /* Indicates timeout, no navigation occurred. */;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What could be causing the ERROR TypeError in an Angular form where "_co.service.formData" is undefined?

My attempt to create a form in Angular 7 has resulted in an error message: ERROR TypeError: "_co.service.formData is undefined" Here is the HTML code for the component: <form (sumbit)="signUp(form)" autocomplete="off" #form="ngForm"> <div clas ...

How to locate and remove an object in Angular 6

What is the method to remove an object from a list of objects using an id number in Angular 6 with TypeScript? EntityService.ts import { Injectable } from '@angular/core'; import { Entity } from '../../models/entity'; @Injectable({ ...

Issues persist with debugger functionality in browser development tools following an upgrade from Angular 8 to version 15

After upgrading from Angular version 8 to version 15, I've encountered an issue where the debugger is not functioning in any browser's developer tools. Can anyone provide some insight on what could be causing this problem? Is it related to the so ...

Expanding the HTTP Get URL with a click in Ionic 2 and Angular 2

I recently performed a search for my ionic app, which fetches data from an api using a http get method as shown below static get parameters() { return [[Http]]; } searchRecipes(id) { var url = 'http://api.yummly.com/v1/api/recipes?_app_id=// ...

What is the best method for translating object key names into clearer and easier to understand labels?

My backend server is sending back data in this format: { firstName: "Joe", lastName: "Smith", phoneNum: "212-222-2222" } I'm looking to display this information in the frontend (using Angular 2+) with *ngFor, but I want to customize the key ...

What is the reason that the name property does not display anything in the Edge browser after compression?

Currently, I'm using a module that utilizes various functions like Not, And, type, and typeIs to construct a query string based on the content type it is searching for. However, there seems to be an issue with one of these functions, particularly the ...

Should private members be kept confidential during program execution?

While Typescript's "private" members may not be truly private at runtime, traditional closures maintain the privacy of their members. Is there value in ensuring that private members remain private during runtime? ...

Why does TypeScript combine the types of both indices when yielding a tuple?

In my generator function, I am yielding an array containing values of type [number, object]. By using a for...of loop to iterate over the function and destructuring the values with for (const [k, v] of iterator()), I noticed that the type of v is number | ...

Creating an Angular service that checks if data is available in local storage before calling an API method can be achieved by implementing a

I am currently working on developing an Angular service that can seamlessly switch between making actual API calls and utilizing local storage within a single method invocation. component.ts this.userService.getAllUsers().subscribe(data => { conso ...

Encountering a challenge in Angular 8: Unable to locate a supporting object matching '[object Object]'

I am having an issue trying to retrieve the Spotify API from the current user's playlists. While I can see it in my console, when I attempt to insert it into HTML, I encounter the following error: ERROR Error: Cannot find a differ supporting object ...

Evaluating file selection and uploading functionality within Spectron

Currently, I am faced with the challenge of writing a test for an electron GUI that includes a choose file dialog. Unfortunately, I do not have access to the inner workings of the GUI. Here is the code snippet I have written: await app.client.chooseFile( ...

Compelling users to provide feedback on an App with the Ionic Framework

As a novice developer, I could use some assistance with implementing ratings in my app. My goal is to show menu items based on whether a user has given my app a 5-star rating. For instance, if a user gives a 5-star rating, I would assign the class "review ...

Error: The specified function in the schema is not valid for the current operation mode

I'm facing an issue with validating a material ui form using Formik and Yup. The error keeps popping up. This is the schema I imported from another file: export const validationSchema = Yup.object({ email: Yup.string() .email('Invalid Ema ...

Is there a way to determine if a puppeteer instance is already active?

I have a requirement to run multiple puppeteer scripts simultaneously. Up until now, I've been using separate browsers for each script, but now I want to use just one browser with the ability to run multiple scripts concurrently on different pages. M ...

Encountering difficulty in establishing a global variable within the subscribe function

I am looking to store the service response in a variable for use in my view. The TypeScript file I am working with is shown below: The MenuService is a custom service that includes a function called getMenus() to fetch all menus from the database. import ...

Fetching data from an API using Observables in Angular

I am facing a challenge with an API endpoint that returns an array of strings in JSON format. My goal is to display these contents on a webpage using an Angular Service. Below is the code snippet I have implemented so far (working with Angular 7): export ...

Tips for resolving the "Access-Control-Allow-Origin" problem in Angular2 with Lite-Server

I am working on an Angular 2 application that interacts with an external API to fetch data. Unfortunately, I do not have the authority to modify the API code. However, I can make changes to the TypeScripts and Lite-Server configuration. Encountered Error ...

Utilizing Puppeteer to interact with dropdown menu options through selection and clicking

To log out, I am trying to use Puppeteer to select and click on a dropdown menu item. This particular menu requires hovering over it with a mouse in order to reveal its options, as opposed to clicking directly. When attempting to copy the selector for th ...

Creating a fresh dataset using a 2D array in node-gdal-async

I'm facing a challenge in JavaScript where I need to create a new dataset from a 2D array. Despite my efforts, I can't seem to figure out the necessary steps from the documentation. It seems that in order to create this new dataset, I must utili ...

How can I utilize the color prop in the theme file to style new variants more comprehensively with MUI theming?

I am working on creating a custom variant for an MUI button where the color specified in the color prop should be applied as both the border and text color. While the MUI documentation offers a suggested approach, it requires addressing each available col ...