Могу ли я просмотреть цикл событий браузера, чтобы узнать порядок выполнения JS, запланированного для выполнения?

Я унаследовал кодовую базу, в которой порядок выполнения JS не ясен, поскольку есть много вызовов setTimeout, глобальных переменных и неработающих цепочек промисов. Вместо того, чтобы вручную отслеживать каждый путь выполнения, я хотел бы зафиксировать то, что JS запланировано для выполнения в очереди сообщений браузера за определенный период времени или в ответ на событие.

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

Учитывая, что сценарии JS — это намечено к исполнению, как я могу увидеть порядок, в котором JS ставится в очередь?

Я начал с чего-то подобного, но это не дает мне полностью надежной временной шкалы.

const {
  setTimeout,
  setInterval,
} = window;

window._jsq = [];

window._record = f => {
  window._jsq.push([f, new Error().stack]);
};

window.setTimeout = (...a) => {
  window._record(a[0]);
  return setTimeout.apply(window, a);
};

window.setInterval = (...a) => {
  window._record(a[0]);
  return setInterval.apply(window, a);
};

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

matanster 24.08.2021 21:02
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
1 200
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Нет встроенного инструмента автоматической отладки для отслеживания цикла событий вашего браузера. Чтобы отслеживать цикл событий браузера, вы должны явно отслеживать события, которые вас интересуют, и передавать их в DevTool (в данном случае Chrome):

monitorEvents(document.body, "click");

Подробнее о мониторинге событий в Chrome Dev Tools

Примечание №1: Вы не знаете, как называются пользовательские события. Они могут не отправлять событие в DOM (например, некоторые библиотеки реализуют свои собственные системы регистрации и обработки событий), поэтому нет общего способа узнать, когда вызываются прослушиватели событий, даже если вы можете отслеживать отправку события.

Некоторые библиотеки также имитируют всплытие событий, но опять же, если вы не знаете тип события, вы не можете его прослушать.

Однако вы можете реализовать свою собственную систему управления событиями и реализовать функцию для прослушивания всех событий, для которых установлены слушатели, или событий, отправленных с помощью вашей системы.

Ссылка: Как я могу отслеживать все пользовательские события, генерируемые в браузере?

Заметка 2: современный подход JS к событиям (IE: React/Redux) предполагает отправку ДЕЙСТВИЙ вместо событий. Поскольку действия часто являются logged для целей time-travel, мониторинг событий в этом случае не нужен.

Да, вроде бы так, но это настоящий облом. Браузерные JS-приложения находятся на том этапе, когда трассировка выходит далеко за рамки событий, поэтому я удивлен, что такая проблема не привлекла большего внимания. Я позволю этой теме немного поиграть, чтобы посмотреть, есть ли какие-либо другие идеи.

Sage Gerard 01.02.2019 16:18

Спасибо за правки! Даже с отслеживанием событий и действий я хотел бы отслеживать JS, запланированные для выполнения такими формами, как (() => { setTimeout(f) asyncFunc() })(). Преимущество такого отслеживания в том, что оно не должно зависеть от реализации приложения.

Sage Gerard 01.02.2019 16:34

В реакции/редуксе также отправить форму является отправкой ДЕЙСТВИЯ, а не отправкой события. Настоящая проблема описана в примечании 1, так как библиотеки часто реализуют прослушиватель функций и обертки с пользовательским всплытием.

Mosè Raguzzini 01.02.2019 16:43
Ответ принят как подходящий

Я рассмотрю свой вопрос с точки зрения фрагмента OP. Исправления приветствуются.

Предполагая, что вы не можете видеть очередь сообщений (или, по крайней мере, сценарии в очереди), вы все равно можете видеть код, который является планирование другим JS, и код, который по расписанию для запуска. Таким образом, возможно отслеживание обоих независимо друг от друга.

Это не все хорошие новости, потому что вам все еще нужно проделать работу, чтобы 1) адаптировать это отслеживание к различным способам планирования JS и 2) понять, что вы фиксируете.

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

const { setTimeout } = window;

// For visibility in DevTools console
window._schedulers = [];
window._calls = [];

const wrap = f => {
  const { stack } = new Error();

  window._schedulers.push([stack, f]);

  return (...a) => {
    window._calls.push([stack, f, a]);

    return f(...a);
  };
};

window.setTimeout = (f, delay, ...a) => {
  return setTimeout.apply(window, [wrap(f), delay].concat(a));
}

Тем не менее, это всего лишь один случай, и он ничего не говорит о том, когда начинать/останавливать мониторинг и о потенциальных триггерных точках, когда отслеживаемость является проблемой, как упомянул Мозе Рагуццини. В случае промисов этот ответ вызывает средства проверки Bluebird.

Похоже, что до тех пор, пока не появится больше нативных инструментов, которые визуализируют поставленные в очередь сценарии и связанную с ними информацию, вы застрянете, собирая и анализируя данные вручную.

Другие вопросы по теме