Javascript-форум (https://javascript.ru/forum/)
-   Node.JS (https://javascript.ru/forum/node-js-io-js/)
-   -   Nightmare Js не возвращает NodeList (https://javascript.ru/forum/node-js-io-js/78215-nightmare-js-ne-vozvrashhaet-nodelist.html)

loksvem 10.08.2019 22:34

Nightmare Js не возвращает NodeList
 
Здравствуйте. Я использую Nightmare JS в Node Js проекте. Вопрос по этому коду:
async function someFunc() { 
    let nightmare; 
    try {   nightmare = Nightmare({show: true, typeInterval: 10, waitTimeout: 5000});
                    await nightmare
                        .goto(`https://example.com`)
                        .click(".button")
                        .wait(".someClass")

                    let result = await nightmare.evaluate(function () {

                        return document.querySelectorAll(".someClass");
                    });

                    console.log(result);

    } catch (error) { 
    throw error; 
    } finally { 
    await nightmare.end(); 
    } 
}


"someClass" содержит несколько элементов(например,3). Я хочу получить в result NodeList, но я получаю только пустой объект. Этот код работает, только если я сразу возвращаю текстовое значение, например так:

return document.querySelectorAll(".someClass")[0].textContent;


Почему я не могу вернуть NodeList в result ?

Audaxviator 19.08.2019 18:44

Знаете, я уж отвечал на этот вопрос - так сказать, "в практическом смысле", - потом удалил свой ответ (раз он спрашивающему не интересен, то чего им маячить?)
Но теперь я ещё раз на него отвечу - на этот раз "по существу". Зачем? -- А потому что мне обидно, что единственный нормальный русскоязычный форум про Node.js выглядит умирающим.
Итак, ответ по существу.

Когда-то давно умные люди придумали специальное устройство ("девайс") для общения в сети Энторнеты, оно называется "браузер". Это устройство умеет делать только три вещи - изготовлять из html-строки "документ-объектную модель" (DOM), разукрашивать её (DOM) всякими цветами и размерами (CSS) и динамически - если надо - её изменять (JavaScript) в рамках полученного "документа". Больше это тупое устройство - "браузер" - ничего делать не умеет.

Обратим внимание на его последнее (в списке) умение.
Что делает в браузере код на языке JavaScript типа такого?
document.querySelectorAll(".someClass");

Поскольку тупой браузер - при помощи своего первого умения - уже построил из "документа" (т.е., фактически, из банальной строки, полученной в виде октет-стрима по интернетам) "документ-объектную модель", то данный код имеет возможность обратиться к этой самой DOM и выбрать из неё (из объекта - выбрать подобъекты) кусочки, удовлетворяющие условиям выборки. И если мы в консоле браузера напишем магические букавы:
console.log(document.querySelectorAll(".someClass");)

то тупой браузер нам тут же, в консоль, и напишет искомую NodeList, т.е. "СПИСОК УЗЛОВ DOM (document-object-model)".

Проблемка заключается в том, что NodeList ("список узлов DOM") существует только в браузере.

А что делает крутой модуль Nightmare? (я его попробовал - он, и вправду, крутой)
1. Делает запрос по указанному URL и получает в ответ html-строку в виде октет-стрима.
2. Вызывает браузер Chromium (как он есть "ядро" десктопного приложения Электрон) и просит создать из полученного "документа(строки)" DOM.
3. На языке JavaScript обращается к созданной DOM с запросом коллекции
document.querySelectorAll(".someClass");
и получает ответ в виде "кусочков подобъектов, собранных из объекта"... в виде чего?...
4. Поскольку Nightmare - это не тупой браузер, то она получает результат своего запроса - в виде той самой СТРОКИ, которую браузер когда-то получил и интерпретировал как "Документ-Объектную-Модель".

Nightmare - это не браузер, она не умеет оперировать "узлами DOM" (теми самыми, которыми браузер так услужливо изображает нам у себя в консоли в ответ на наш запрос). В качестве ответа она умеет понять только "строку".

Ну всё, я устал.
Если кто не согласен с ответом - милости прошу разъяснить детали.

А если не последует разъяснений - ну и хуй с ним, с форумом.

SuperZen 19.08.2019 20:34

5 копеек называются https://github.com/GoogleChrome/puppeteer

но оно опять не для всех )

Audaxviator 20.08.2019 13:49

Да вообще, это вопрос про "типы данных". В javascript он же никогда не стоит, как в "правильных" языках, но это он - в таком вот, несколько неожиданном виде.
Мы же не удивимся, если попытаться открыть в каком-нибудь приложении файл, тип которого это приложение не поддерживает (ну там, открыть html-документ в Фотошопе), и он там не откроется. Здесь примерно тот же случай. "Узлы DOM" и их коллекции (NodeList) - это, вроде бы, объекты, но специфические - браузерные объекты, тип которых Nightmare (да видимо, Нода вообще) не понимает. И функция, которая передаётся в аргумент метода evaluate, должна вернуть какой-нибудь понятный ей тип данных - строку или массив строк, или объект с ключами и значениями-строками.
Вот, собсна, и всё.

SuperZen 20.08.2019 13:55

сам автор nightmarejs уже сказал, что это все устарело и он больше не разрабатывает этот проект

Audaxviator 20.08.2019 13:59

Да это не важно. Express тоже "устарел", и его никто больше не разрабатывает. А его знаменитый аффтар сказал, что Нода - это отстой, и он теперь пишет на Go.
И как дальше жить?

SuperZen 20.08.2019 14:22

я думаю: пока жив web на javascript'е, nodejs не умрет тоже ) ну или как go будет манипулировать dom'ом ) без js? Ну максимум mvc, и приплыли )

https://stackoverflow.com/q/29886552

By default, {} objects are not iterable, but why? Would the disadvantages outweigh the potential benefits of objects being iterable? What are the issues associated with this?

In addition, because {} objects are different from "Array-like" collections and "iterable objects" such as NodeList, HtmlCollection, and arguments, they can't be converted into Arrays.

https://github.com/segmentio/nightmare/issues/617

-- отсюда, наверное, вывод: надо парсить nodeList в evalute, а не возвращать в node и парсить там )... или возвращать document.body.innerHTML в нод, в нод создавать инстанс дом'а, и его парсить... а что будет если вернуть document.querySelector(".someClass")
(не querySelectorAll)... ))

Audaxviator 20.08.2019 14:37

Это всё равно, document.querySelector(".someClass") вернёт один непонятный "узел". Можно так -
return document.querySelector(".someClass").parentElement.innerHTML

А внутри этой функции можно делать что угодно, только возвращать понятные результаты - elem.id или elem.innerHTML, или elem.textContent, elem.href, elem.src - или массивы этого всего собирать.
Но - внутри этой функции, она как раз для этого и предназначена. Всё, что в её теле пишется, это клиенткий javascript в браузере, любой.

SuperZen 20.08.2019 15:18

это должно быть понятно, что в evalute и надо все парсить...


Часовой пояс GMT +3, время: 08:19.