Добавление пользовательского метода в объект puppeteer.Page - PullRequest
2 голосов
/ 11 июля 2019

Я хотел бы добавить пользовательские методы к объекту puppeteer.Page, чтобы я мог вызывать их следующим образом:

let page = await browser.newPage();
page.myNewCustomMethod();

Вот один из многих созданных мной пользовательских методов.Он находит первый доступный элемент по выражению XPath, используя массив выражений:

const findAnyByXPath = async function (page: puppeteer.Page, expressions: string[]) {
    for (const exp of expressions) {
        const elements = await page.$x(exp);

        if (elements.length) {
            return elements[0];
        }
    }

    return null;
}

Я должен вызвать его так ...

let element = await findAnyByXPath(page, arrayOfExpressions);

Мне это кажется страннымв редакторе, особенно в регионе, где вызываются многие пользовательские методы.Это выглядит для меня немного «вне контекста».Поэтому я бы предпочел вызвать его так:

page.findAnyByXPath(arrayOfExpressions);

Я знаю, что существует метод page.exposeFunction , но это не то, что я ищу.

Как это можно сделать?

1 Ответ

1 голос
/ 12 июля 2019

Вы можете сделать это?Да.

Вы можете расширить любой объект в JavaScript, изменив его прототип.Чтобы добавить функцию к объекту Page, вы можете получить доступ к прототипу объекта Page, используя свойство __proto__.

Вот простой пример добавленияфункция customMethod для всех объектов Page:

const page = await browser.newPage();
page.__proto__.customMethod = async function () {
    // ...
    return 123;
}
console.log(await page.customMethod()); // 123

const anotherPage = await browser.newPage();
console.log(await anotherPage.customMethod()); // 123

Обратите внимание, что сначала вам нужен объект Page, чтобы получить доступ к прототипу, поскольку функция-конструктор (или класс) сама не предоставляется.

Должны ли вы сделать это?Нет.

Вы, вероятно, уже заметили красные предупреждения на связанных документах MDN выше.Прочитайте их внимательно.В общем, не рекомендуется менять прототип объектов, которые вы используете и не создали сами.Кто-то создал прототип, и он не ожидал, что кто-нибудь возится с ним.За дополнительной информацией обращайтесь к этому вопросу:

Как это сделатьэто вместо этого?

Вместо этого вы должны просто использовать свои собственные функции.Нет ничего плохого в том, чтобы иметь свои собственные функции и вызывать их с page в качестве аргумента, подобного следующему:

// simple function
findAnyByXPath(page);

// your own "namespace" with more functionality
myLibrary.findAnyByXPath(page);
myLibrary.anotherCustomFunction(page);

Обычно вы также можете расширить класс Page, но в этом случае библиотека неэкспорт самого class.Следовательно, вы можете создать только класс-оболочку, который выполняет те же функции внутри, но предлагает больше функциональности сверху.Но это был бы очень сложный подход, и он действительно стоит усилий в этом случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...