angular - 迁移到 Angular 12 后 Cytoscape.js“超出最大调用堆栈大小”错误
问题描述
最近,我将 Angular 应用程序从版本 10 迁移到 12。自从我迁移后,使用 cytoscape.js 可视化图形的组件产生以下错误:
ERROR RangeError: Maximum call stack size exceeded
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
当我通过像这样调用其构造函数来初始化 Cytoscape 时会发生此错误:
this.cytoscape = cytoscape({
container: document.getElementById('cytoscape-canvas-area'), //This line causes the error
elements: {...initialGraph} as any,
style: GRAPH_STYLES,
layout: GRAPH_LAYOUT,
autoungrabify: true,
boxSelectionEnabled: true,
panningEnabled: true,
userPanningEnabled: true,
userZoomingEnabled: true,
zoomingEnabled: true,
zoom: 1,
minZoom: 0.1,
maxZoom: 10,
});
在进行故障排除时,我发现只要我在代码中标记了上面示例中的行,就会发生错误。我已经检查过是否document.getElementById('cytoscape-canvas-area')
返回了某些东西,就是这种情况。
这是我的 package.json 与所有版本:
"dependencies": {
"@angular/animations": "~12.2.0",
"@angular/common": "~12.2.0",
"@angular/compiler": "~12.2.0",
"@angular/core": "~12.2.0",
"@angular/elements": "^12.2.0",
"@angular/forms": "~12.2.0",
"@angular/localize": "^12.2.0",
"@angular/platform-browser": "~12.2.0",
"@angular/platform-browser-dynamic": "~12.2.0",
"@angular/router": "~12.2.0",
"@fortawesome/angular-fontawesome": "^0.9.0",
"@fortawesome/fontawesome-svg-core": "^1.2.28",
"@fortawesome/free-solid-svg-icons": "^5.13.0",
"@fortawesome/pro-regular-svg-icons": "^5.15.3",
"@ngx-translate/core": "^13.0.0",
"@ngx-translate/http-loader": "^6.0.0",
"@types/cytoscape": "^3.14.17",
"@types/jest": "^26.0.24",
"angular-font-awesome": "^3.1.2",
"bootstrap": "^4.4.1",
"concurrently": "^5.1.0",
"cytoscape": "^3.19.1",
"cytoscape-canvas": "^3.0.1",
"cytoscape-cxtmenu": "^3.1.2",
"cytoscape-dagre": "^2.3.2",
"document-register-element": "^1.7.2",
"http-server": "^0.12.1",
"jest": "^27.0.6",
"jest-preset-angular": "^9.0.5",
"live-server": "^1.2.1",
"moment": "^2.26.0",
"ngx-bootstrap": "^5.3.2",
"ngx-build-plus": "^10.1.1",
"rxjs": "^6.6.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4" },
"devDependencies": {
"@angular-devkit/build-angular": "~12.2.0",
"@angular/cli": "^12.2.0",
"@angular/compiler-cli": "~12.2.0",
"@angular/language-service": "~12.2.0",
"@types/node": "^12.11.1",
"codelyzer": "^6.0.0",
"cytoscape-edgehandles": "^3.6.0",
"ts-node": "~7.0.0",
"tslint": "~6.1.0",
"typescript": "~4.3.5"
},
如果有人可以帮助我,我会很高兴:)
更新 1
当我设置一个新的 Angular 12 应用程序并添加 Cytoscape.js 时,一切正常。该错误仅出现在此项目中。我使用 ng update 并遵循 Angular 的官方更新指南进行了迁移。不幸的是,我不能只使用一个新项目,因为这个项目正在生产中。
更新 2
this.cytoscape = cytoscape(...)
ngOnChanges
在我从远程服务器获取一些数据后在循环中调用。我已经检查了传递数据的结构,它是正确的。
this.graphService.getByUuidWithNodesAndEdges(uuid).subscribe(graphData => {
this.cytoscapeService.createCanvas(graphData);
});
cytoscapeService
是我自己创建的一个服务,它管理与框架相关的所有代码。
createCanvas(initialGraph: GraphCyo) {
this.cytoscape = cytoscape({
container: document.getElementById('cytoscape-canvas-area'),
elements: {...initialGraph} as any,
...otherConfig
});
}
更新 3
该错误与错误的 Angular Lifecycle Hook 或加载大量数据无关。当我在视图中添加一个按钮时也会出现相同的异常,该按钮会使用一些虚拟数据触发 cytoscape 的初始化:
<div style="background: #ffcc00; height: 500px; width: 500px" id="test-container-cy-bug">
<button style="position: fixed; left: 0; bottom: 0; z-index: 99" (click)="initCytoscapeCanvas()">Init!</button>
然后是init方法:
initCytoscapeCanvas() {
this.cytoscape = cytoscape({
container: document.getElementById('test-container-cy-bug'),
elements: [
{
group: 'nodes',
data: {
id: '1'
}
},
{
group: 'nodes',
data: {
id: '2'
}
},
{
group: 'edges',
data: {
id: 'e',
source: '1',
target: '2'
}
}
]
});
}
单击Init!
按钮时出现错误:
ERROR RangeError: Maximum call stack size exceeded
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
at V.y.<computed>.get (polyfills.js:1)
defaultErrorLogger @ core.js:6479
handleError @ core.js:6527
handleError @ core.js:10938
executeListenerWithErrorHandling @ core.js:15311
wrapListenerIn_markDirtyAndPreventDefault @ core.js:15346
(anonymous) @ platform-browser.js:561
ZoneDelegate.invokeTask @ zone.js:421
onInvokeTask @ core.js:28659
ZoneDelegate.invokeTask @ zone.js:420
Zone.runTask @ zone.js:188
ZoneTask.invokeTask @ zone.js:503
invokeTask @ zone.js:1671
globalZoneAwareCallback @ zone.js:1697
解决方案
推荐阅读
- c++ - 现代编译器如何优化此代码
- php - 为什么我的变量值设置为 false,即使它设置为 true?
- kubernetes - 以单词开头时删除所有 pod(pod 名称不完整)
- jquery - 如何使用 JQuery animate() 作为切换?
- rust - 并行运行循环组合
- arrays - 如何知道每个元素在数组中出现的次数?
- r - mapply 没有相同的返回数据类型
- docker - '/bin/sh: go: not found' 在 'docker:dind' 容器中
- c++ - 如何将 MFC 项目从 Visual Studio 2008 升级到 Visual Studio 2010(或更高版本)?
- azure - Azure Data Lake 在存储用于 Power BI 可视化的 SQL 数据库方面有多好?