Перейти к содержимому

Cannot read properties of undefined - разбор причин на витрине

Скрипт витрины падает в консоли браузера с сообщением про чтение свойства у неопределённого значения. Разбираем причины по убыванию частоты.

С чего начать

Смотрим, что именно оказалось неопределённым:

console.log(typeof BX, typeof BX.UI, typeof window.VendorGallery);
// undefined у любого из них означает неподключённое расширение или свой файл

Первое, что проверяют на витрине, - подключены ли нужные библиотеки на конкретной странице. Половина таких ошибок объясняется тем, что расширение подключено на одной странице, а скрипт работает на другой.

Проверяем, существует ли узел разметки:

const node = document.querySelector('.js-gallery');
console.log(node); // null означает, что разметки ещё или уже нет

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

Печатаем ответ сервера целиком:

BX.ajax.runComponentAction('vendor:gallery', 'load', { mode: 'class' })
.then((response) => console.log(JSON.stringify(response)));
// полезная нагрузка лежит в поле данных, а ошибки приходят отдельным списком

Смотрим, какой файл скрипта реально отдан браузеру:

Окно терминала
curl -s https://example.com/catalog/ | grep -oE 'src="[^"]*(gallery|kernel)[^"]*"' | head
# объединение статики отдаёт один общий файл, и в нём может лежать старая версия

Отключаем объединение статики на время разбора:

printf("объединение js=%s css=%s\n",
\COption::GetOptionString('main', 'optimize_js_files'),
\COption::GetOptionString('main', 'optimize_css_files'));
// на время разбора объединение выключают, потом обязательно возвращают

Причины

  1. Расширение или свой файл не подключены примерно 30% случаев

    ПризнакВ консоли неопределён сам объект библиотеки, а не его отдельное свойство.

    ПроверкаПечатаем тип нужного объекта в консоли именно на той странице, где падает скрипт.

    Что делатьПодключаем расширение или свой файл на этой странице средствами платформы, а не тегом.

  2. Узла разметки ещё нет на момент запуска примерно 20% случаев

    ПризнакОшибка возникает сразу при загрузке страницы, а по кнопке всё работает.

    ПроверкаПечатаем результат поиска узла: пустое значение сразу подтверждает версию.

    Что делатьПереносим запуск после разметки блока или откладываем его до готовности документа.

  3. Ответ сервера отличается от ожидаемого примерно 20% случаев

    ПризнакОшибка появляется после запроса к серверу, а не при загрузке страницы.

    ПроверкаПечатаем ответ целиком и сверяем структуру полей с тем, что ждёт код.

    Что делатьЧитаем полезную нагрузку из поля данных ответа и обрабатываем список ошибок отдельно.

  4. Опечатка или переименованное поле примерно 15% случаев

    ПризнакОшибка появилась сразу после правки шаблона или переименования параметра.

    ПроверкаСравниваем имя поля в разметке, в коде скрипта и в ответе сервера построчно.

    Что делатьПриводим имена к одному виду и добавляем проверку наличия поля перед обращением.

  5. Браузер получил старую версию файла примерно 15% случаев

    ПризнакОшибка воспроизводится не у всех и пропадает после жёсткого обновления страницы.

    ПроверкаСмотрим адрес отданного файла и его метку версии в исходном коде страницы.

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

Частые вопросы

Почему ошибка воспроизводится не у всех?

Обычно дело в кэше браузера или в объединённом файле статики. У части посетителей лежит старая версия скрипта, у остальных - новая.

Как понять, где именно падает код?

По стеку вызовов в консоли: он показывает файл и строку. При объединении статики строку смотрят в исходном файле, а не в общем.

Помогают ли проверки перед обращением?

Да, они превращают падение скрипта в тихий пропуск блока. Причину при этом всё равно ищут: тихий пропуск - не решение, а смягчение.

Почему на стенде всё работает?

На стенде обычно выключено объединение статики и кэш браузера чистый. Проверять такие ошибки надо в тех же условиях, что и на бою.

Стоит ли откладывать весь код до готовности документа?

Нет, это замедляет отклик страницы. Откладывают только то, что действительно зависит от разметки, а остальное запускают сразу.

Смежное

Первоисточник