最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Can I view the event loop of a browser to learn the order of JS scheduled for execution? - Stack Overflow

programmeradmin1浏览0评论

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. 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.

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.

Given that JS scripts are scheduled for execution, how I can see the order in which JS gets queued?

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

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. 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.

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.

Given that JS scripts are scheduled for execution, how I can see the order in which JS gets queued?

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);
};
Share Improve this question edited Feb 1, 2019 at 15:23 asked Feb 1, 2019 at 15:07 Sage GerardSage Gerard 1
  • I would say that this would help trace performance aspects and the time that event callbacks remain queued, even if there is less chaos or plexity in one's application – matanox Commented Aug 24, 2021 at 19:02
Add a ment  | 

2 Answers 2

Reset to default 3

I'll take a crack at my own question from the angle of the OP snippet. 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. 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.

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. 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. In the case of Promises, this answer calls out Bluebird's checking facilities.

It seems that until more native tools e out that visualize queued scripts and related info, you are stuck collecting and analyzing the data by hand.

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:

monitorEvents(document.body, "click");

More info about monitoring events in Chrome Dev Tools

Note #1: You don't know how custom events are called. They may not dispatch an event into the DOM (e.g. 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.

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. As actions are often logged for time-travel purpose, monitoring events in this case is unnecessary.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论