В Typescript, как мне поддерживать тип объектов при сохранении и последующем доступе к указанному объекту из массива? - PullRequest
1 голос
/ 17 мая 2019

В машинописи я заметил, что когда я беру сложный объект и помещаю его в массив, когда я пытаюсь получить доступ к этому объекту из массива, он теряет свой тип и вместо этого просто становится объектом типа.

Например,

let myArray = return await this.browser.evaluate((sel: string) => Array.from(document.querySelectorAll(sel)), selector)

document.querySelectorAll(sel) возвращает NodeList<Element>, равное ArrayLike.Array.from должен преобразовать NodeList в массив элементов, но как только массив сформирован, все элементы массива теряют свой Element тип

У меня есть функция, которая будет принимать только параметры типа Element, но когда я пытаюсь передать myArray[0] в качестве параметра для указанной функции, я получаю ошибку: Error: Unsupported target type: object

Я пробовал так много разных вещей, чтобы попытаться получить массив для поддержания еготип объекта, который будет трудно объяснить каждому из них.Мне интересно, как я могу создать массив Element с, и чтобы они продолжали быть Element с при последующем доступе вместо общих object s

Вот немного больше контекста в тестировании, которое явсе готово

Я перехожу на эту страницу: https://www.w3schools.com/html/html_tables.asp и селектор, который я передаю для оценки, равен table[id="customers"] tbody tr Это должно совпадать с 6 строками в таблице.

let test = await this.browser.evaluate((sel: string) => 
Array.from(document.querySelectorAll(sel)), selector)
console.log('testy1: ', test)
console.log('testy2: ', test[0])
console.log('testy3: ', typeof(test[0]))

Когда я запускаю приведенный выше код, это вывод, который я получаю в журнале консоли:

testy1:  [ {}, {}, {}, {}, {}, {}, {} ]
testy2:  {}
testy3:  object

Кажется, это совпадает с захватом элементов со страницы, потому что он правильно возвращает 6 элементов,но может проблема в том, что возвращаемые объекты пусты?Я не уверен.

Я думаю, что моя проблема может быть связана с этим вопросом: puppeteer page.evaluate querySelectorAll возвращает пустые объекты

, но решение этого вопроса не 'это не работает для меня, потому что href не является свойством типа объекта Element

1 Ответ

1 голос
/ 17 мая 2019

Проблема здесь в том, что функция, которую вы передаете page.evaluate, запускается в контексте браузера (внутри страницы браузера).Для отправки результатов из контекста браузера в среду Node.js результаты сериализуются.

См. Тип возврата в документах для page.evaluate:

Returns: Promise<<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#Description" rel="nofollow noreferrer"> Serializable > Обещание, которое разрешается до возвращаемого значения pageFunction

Здесь Serializable означает, что ваши данные будут переданы в среду Node.js через JSON.stringify и там автоматически разбирается для вас.Этот процесс, однако, удалит все несериализуемые свойства объектов.По этой причине вы получаете много пустых объектов.

Получить дескрипторы элементов в кукловоде

Чтобы получить дескриптор элемента на странице, вам нужно использовать page.$, который создает объект (в вашей среде Node.js), который связан с элементом в контексте браузера.Эти дескрипторы также могут передаваться на page.evaluate вызовы.Для запроса нескольких элементов вы можете использовать функцию page.$$.

Пример кода

Вот пример, который сначала запрашиваетэлемент, а затем передает дескриптор элемента в функцию оценки для чтения атрибута.

const elementHandle = await page.$('a');
const result = await page.evaluate(el => el.href, elementHandle);

Использование TypeScript

Проблема, связанная с TypeScript, заключается в том, что TypeScript не может правильно предсказать типв этом сценарии.Для компилятора TypeScript это выглядит как обычный вызов функции, тогда как в действительности функция отправляется клиенту для выполнения.Следовательно, в этом случае вы должны привести тип самостоятельно, иначе Typescript просто примет any в качестве типа аргумента:

const elementHandle = await page.$('a');
const result = await page.evaluate((el: { href: string }) => el.href, elementHandle);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...