简体   繁体   English

我可以查看浏览器的事件循环以了解预定执行的JS的顺序吗?

[英]Can I view the event loop of a browser to learn the order of JS scheduled for execution?

I've inherited a codebase where the order in which JS executes is not clear since there's a lot of setTimeout calls, globals, and broken Promise chains. 我继承了一个代码库,其中存在大量setTimeout调用,全局变量和断开的Promise链,因此JS执行的顺序不清楚。 Rather than manually trace every execution path I'd like to capture what JS gets scheduled for execution on the browser's message queue over a time period, or in response to an event. 而不是手动跟踪每个执行路径,我想捕获在某个时间段内或响应事件而计划在浏览器的消息队列上计划执行的JS。

I can see Event Listeners and trace from when one fires, but this is proving too slow in my case. 我可以看到事件侦听器并从事件触发时进行跟踪,但是事实证明这太慢了。 A single click can sprawl out into several scheduled scripts that each mutate a shared state. 只需单击一下,就可以展开成几个计划的脚本,每个脚本都会改​​变共享状态。 This is why I am not considering tracing from event handlers and am instead looking for an overarching timeline for all JS in the application. 这就是为什么我不考虑从事件处理程序进行跟踪,而是在寻找应用程序中所有JS的总体时间表的原因。

Given that JS scripts are scheduled for execution , how I can see the order in which JS gets queued? 鉴于JS脚本已安排执行 ,我如何才能看到JS排队的顺序?

I've started with something like this, but this doesn't give me a fully reliable timeline. 我从这样的事情开始,但这并没有给我一个完全可靠的时间表。

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);
};

There is no built-in automatic debugging tool for monitoring your browser event loop. 没有内置的自动调试工具来监视浏览器事件循环。 In order to monitor the browser's event loop you have to explicity monitor the event that are in your interested in and pass it to the (in this case Chrome's) DevTool: 为了监视浏览器的事件循环,您必须显式监视您感兴趣的事件,并将其传递给(在本例中为Chrome的)DevTool:

monitorEvents(document.body, "click");

More info about monitoring events in Chrome Dev Tools 有关在Chrome开发工具中监视事件的更多信息

Note #1: You don't know how custom events are called. 注意#1:您不知道如何调用自定义事件。 They may not dispatch an event into the DOM (eg some libraries implement their own event registration and handling systems) so there is no general way of knowing when event listeners are being called, even if you can track the dispatch of the event. 他们可能不会将事件调度到DOM中(例如,某些库实现了其自己的事件注册和处理系统),因此即使您可以跟踪事件的调度,也没有通用的方法来知道何时调用事件侦听器。

Some libraries also simulate event bubbling, but again, unless you know the type of event, you can't listen for it. 一些库还模拟事件冒泡,但是同样,除非您知道事件的类型,否则您将无法监听它。

However, you could implement your own event management system and implement a function to listen for all events for which listeners are set or events dispatched using your system. 但是,您可以实现自己的事件管理系统,并实现侦听所有设置了侦听器的事件或使用系统调度的事件的功能。

Ref: How can I monitor all custom events emitted in the browser? 参考: 如何监视浏览器中发出的所有自定义事件?

Note #2: a modern JS approach to events (IE: React/Redux) involves dispatching ACTIONS instead of events. 注意#2:事件的现代JS方法(IE:React / Redux)涉及调度ACTIONS而不是事件。 As actions are often logged for time-travel purpose, monitoring events in this case is unnecessary. 由于经常logged time-travel动作,因此在这种情况下无需监视事件。

I'll take a crack at my own question from the angle of the OP snippet. 我将从OP代码片段的角度来探讨我自己的问题。 Corrections appreciated. 更正表示赞赏。

Assuming you cannot see the message queue (or at least the scripts queued), you can still see the code that is scheduling other JS and the code that is scheduled to run. 假设您看不到消息队列(或至少队列中的脚本),您仍然可以看到正在计划其他JS的代码和计划运行的代码。 So, tracking both independently is possible. 因此,可以独立跟踪两者。

This is not all good news because you still have to do legwork to 1) adapt that tracking to the various ways JS can get scheduled, and 2) make sense of what you capture. 这并不是一个好消息,因为您仍然需要做一些工作,以1)使跟踪适应JS可以安排的各种方式,以及2)了解您捕获的内容。

In the setTimeout case, something quick and dirty like this can at least provide a sense of a scheduling timeline and when things actually happened. setTimeout情况下,像这样的快速而又肮脏的事情至少可以提供一种调度时间表以及实际发生时间的感觉。 That's just a matter of wrapping functions. 这只是包装功能的问题。

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));
}

Still, that's just one case and says nothing about when to start/stop monitoring and the potential trigger points where traceability is a concern as Mosè Raguzzini mentioned. 不过,这只是一种情况,正如MosèRaguzzini所提到的,什么时候开始/停止监视以及潜在的触发点都没有提到任何可追溯性。 In the case of Promises, this answer calls out Bluebird's checking facilities. 对于Promises, 此答案要求Bluebird的检查设施。

It seems that until more native tools come out that visualize queued scripts and related info, you are stuck collecting and analyzing the data by hand. 看起来,除非出现更多本地工具来可视化排队的脚本和相关信息,否则您将不得不手工收集和分析数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM