Различное поведение для page.evaluate и page. $ С последующей функцией - PullRequest
1 голос
/ 13 января 2020

У меня есть страница, которую я загружаю. Работает следующий код page.$eval():

const productName = await page.$eval('h1[role="main"]', el =>
    [].reduce.call(
      el.childNodes,
      (a, b) =>
        a +
        (b.nodeType === 3
          ? b.textContent
              .replace(/[\r\n]+/gm, "")
              .replace(/\s+/g, " ")
              .trim()
          : ""),
      ""
    )
  );

Под работами я имею в виду, что он возвращает название предполагаемого продукта. Я запускаю его в основной функции.

Теперь я хочу передать код своей собственной функции вне исходного контекста (для повторного использования).

Я вызываю функцию внутри основной функции, как this:

  const productName = await page
    .$('h1[role="main"]')
    .then(el => getProductNameFromSelector(el))
    .catch(err => console.log("failure product name", err));

Аутсорсинговая функция выглядит следующим образом:

const getProductNameFromSelector = async el =>
  el
    .evaluate(
      el,
      [].reduce.call(
        el.childNodes,
        (a, b) =>
          a +
          (b.nodeType === 3
            ? b.textContent
                .replace(/[\r\n]+/gm, "")
                .replace(/\s+/g, " ")
                .trim()
            : ""),
        ""
      )
    )
    .then(result => result)
    .catch(err => console.log("error in function", err, el));

Она приводит к следующей ошибке:

failure product name TypeError: Cannot read property 'evaluate' of null
    at reduce (<anonymous>)
    at getProductNameFromSelector (pathToFile.js:395:17)
    at page.$.then.el (pathToFile.js:119:21)
    at process._tickCallback (internal/process/next_tick.js:68:7)

Я должен получить ElementHandle с page.$('h1[role="main"]'). Это говорит undefined хотя.

1 Ответ

1 голос
/ 13 января 2020

Функция evaluate должна ожидать элемент el в качестве аргумента

const getProductNameFromSelector = async el =>
  el
    .evaluate(el =>  //HERE
      [].reduce.call(
        el.childNodes,
        (a, b) =>
          a +
          (b.nodeType === 3
            ? b.textContent
                .replace(/[\r\n]+/gm, "")
                .replace(/\s+/g, " ")
                .trim()
            : ""),
        ""
      )
    )
    .then(result => result)
    .catch(err => console.log("error in function", err, el));

Вы также можете подождать селектор:

const productName = await page
    .waitForSelector('h1[role="main"]')
    .then(el => getProductNameFromSelector(el))
    .catch(err => console.log("failure product name", err));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...