gpt4 book ai didi

angular - 您如何确定是什么触发了 Angular2 中的变化检测检测(调试 ngDoCheck 无限循环)?

转载 作者:太空狗 更新时间:2023-10-29 17:25:09 25 4
gpt4 key购买 nike

我无法进行最小复制,我可以放入 plunkr,但在我的应用程序中,我有一个无限循环,其中无限调用根组件中的 ngDoCheck,所以我'我希望能够确定 实际发生了什么变化。

我查看了在 ngDoCheck 中放置断点的堆栈跟踪中的每个调用,但找不到任何有用的东西。

我知道从 变化检测中触发变化检测会导致这种无限循环(虽然我认为我启用的 Debug模式会捕获它)但我找不到任何手动实例。

是否有任何可以记录或检查的内容可以深入了解导致一轮更改检测的原因?


可能不是很有用,但是在这个循环中有一个堆栈和状态的快照:

ngDoCheck infinite loop

最佳答案

可能有点晚,但仍然可能对某些人有帮助。

我找到了几个解决方案,可以帮助您找到真正导致 CD 循环的原因。

第一个,正如评论中提到的,检查任务的source字段,最简单的方法是

 // put this in any component which is rendered on the page
public ngDoCheck() {
console.log('doCheck', Zone.currentTask.source);
}

这将输出如下内容:

enter image description here

这已经是东西了,你有进一步研究的方向,但还不够完善。

要找到定义操作处理程序的真实位置,我们需要区域的 long-stack-trace 规范。

// add this, for example, in your polyfills file 
import 'zone.js/dist/long-stack-trace-zone';

现在除了任务源之外,我们还可以检查 long-stack-trace 准备的数据

  public ngDoCheck() {
console.log('doCheck', Zone.currentTask.source, Zone.currentTask.data.__creationTrace__);
}

这将输出一个数组:

enter image description here

我们对数组中每个条目的 error 属性感兴趣。从 0 元素开始在控制台中进行调查,然后再进一步。

在这个属性中会有一个像这样的堆栈跟踪:

enter image description here

也许这种方式过于复杂,但这是我通过阅读 Zone 的源代码发现的。如果有人提出更简单的解决方案,我们将非常高兴。

更新1

我创建了一个小片段,可以帮助您提取长堆栈跟踪

function renderLongStackTrace(): string {
const frames = (Zone.currentTask.data as any).__creationTrace__;
const NEWLINE = '\n';

// edit this array if you want to ignore or unignore something
const FILTER_REGEXP: RegExp[] = [
/checkAndUpdateView/,
/callViewAction/,
/execEmbeddedViewsAction/,
/execComponentViewsAction/,
/callWithDebugContext/,
/debugCheckDirectivesFn/,
/Zone/,
/checkAndUpdateNode/,
/debugCheckAndUpdateNode/,
/onScheduleTask/,
/onInvoke/,
/updateDirectives/,
/@angular/,
/Observable\._trySubscribe/,
/Observable.subscribe/,
/SafeSubscriber/,
/Subscriber.js.Subscriber/,
/checkAndUpdateDirectiveInline/,
/drainMicroTaskQueue/,
/getStacktraceWithUncaughtError/,
/LongStackTrace/,
/Observable._zoneSubscribe/,
];

if (!frames) {
return 'no frames';
}

const filterFrames = (stack: string) => {
return stack
.split(NEWLINE)
.filter((frame) => !FILTER_REGEXP.some((reg) => reg.test(frame)))
.join(NEWLINE);
};

return frames
.filter(frame => frame.error.stack)
.map((frame) => filterFrames(frame.error.stack))
.join(NEWLINE);
}

用法:

  public ngDoCheck() {
console.log(renderLongStackTrace());
}

更新2

我发现对于 EventTask,区域的 long-stack-trace 创建了错误的堆栈跟踪,您可以在此处跟踪此问题 https://github.com/angular/zone.js/issues/1195

更新 3

在应用程序 Bootstrap (不适用于生产)之前设置 Error.stackTraceLimit = Infinity; 是值得的,因为带有 angular + zone 的堆栈跟踪可能真的很长。

关于angular - 您如何确定是什么触发了 Angular2 中的变化检测检测(调试 ngDoCheck 无限循环)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43149097/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com