Я унаследовал кодовую базу, в которой порядок выполнения 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);
};



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Нет встроенного инструмента автоматической отладки для отслеживания цикла событий вашего браузера. Чтобы отслеживать цикл событий браузера, вы должны явно отслеживать события, которые вас интересуют, и передавать их в DevTool (в данном случае Chrome):
monitorEvents(document.body, "click");
Подробнее о мониторинге событий в Chrome Dev Tools
Примечание №1: Вы не знаете, как называются пользовательские события. Они могут не отправлять событие в DOM (например, некоторые библиотеки реализуют свои собственные системы регистрации и обработки событий), поэтому нет общего способа узнать, когда вызываются прослушиватели событий, даже если вы можете отслеживать отправку события.
Некоторые библиотеки также имитируют всплытие событий, но опять же, если вы не знаете тип события, вы не можете его прослушать.
Однако вы можете реализовать свою собственную систему управления событиями и реализовать функцию для прослушивания всех событий, для которых установлены слушатели, или событий, отправленных с помощью вашей системы.
Ссылка: Как я могу отслеживать все пользовательские события, генерируемые в браузере?
Заметка 2: современный подход JS к событиям (IE: React/Redux) предполагает отправку ДЕЙСТВИЙ вместо событий. Поскольку действия часто являются logged для целей time-travel, мониторинг событий в этом случае не нужен.
Да, вроде бы так, но это настоящий облом. Браузерные JS-приложения находятся на том этапе, когда трассировка выходит далеко за рамки событий, поэтому я удивлен, что такая проблема не привлекла большего внимания. Я позволю этой теме немного поиграть, чтобы посмотреть, есть ли какие-либо другие идеи.
Спасибо за правки! Даже с отслеживанием событий и действий я хотел бы отслеживать JS, запланированные для выполнения такими формами, как (() => { setTimeout(f) asyncFunc() })(). Преимущество такого отслеживания в том, что оно не должно зависеть от реализации приложения.
В реакции/редуксе также отправить форму является отправкой ДЕЙСТВИЯ, а не отправкой события. Настоящая проблема описана в примечании 1, так как библиотеки часто реализуют прослушиватель функций и обертки с пользовательским всплытием.
Я рассмотрю свой вопрос с точки зрения фрагмента 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.
Похоже, что до тех пор, пока не появится больше нативных инструментов, которые визуализируют поставленные в очередь сценарии и связанную с ними информацию, вы застрянете, собирая и анализируя данные вручную.
Я бы сказал, что это поможет отслеживать аспекты производительности и время, в течение которого обратные вызовы событий остаются в очереди, даже если в приложении меньше хаоса или сложности.