我继承了一个代码库,其中 JS 的执行顺序不清楚,因为有大量 setTimeout
调用、全局变量和损坏的 Promise 链。我不想手动跟踪每个执行路径,而是想捕获在一段时间内安排在浏览器消息队列上执行的 JS 或响应事件的内容。
我可以看到事件监听器并在事件监听器触发时进行跟踪,但在我的情况下这被证明太慢了。一次单击可以扩展到多个计划脚本,每个脚本都会改变一个共享状态。这就是为什么我不考虑从事件处理程序进行跟踪,而是寻找应用程序中所有 JS 的总体时间线。
假设 JS 脚本是 scheduled for execution ,如何查看 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);
};
最佳答案
我将从OP片段的 Angular 来分析我自己的问题。感谢指正。
假设你看不到消息队列(或者至少看不到排队的脚本),你仍然可以看到调度其他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));
}
不过,这只是一个案例,并没有说明何时开始/停止监控以及 Mosè Raguzzini 提到的可追溯性问题的潜在触发点。对于 Promise,this answer调用 bluebird 的检查设施。
看来,在更多可以可视化排队脚本和相关信息的 native 工具出现之前,您似乎只能手工收集和分析数据。
关于javascript - 我可以查看浏览器的事件循环来了解 JS 的执行顺序吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54482123/