动态引入Chart.js CDN后调用报Chart未定义错误是什么原因?
问题原因与解决方案
报错核心原因
动态创建的<script>标签加载外部JS资源属于异步行为:你将script标签插入document.head后,浏览器仅会开始后台下载对应的Chart.js资源,不会阻塞后续代码执行。
你在点击第一个按钮后立刻点击第二个按钮时,Chart.js还未完成下载和全局挂载,所以draw函数执行时找不到全局Chart构造函数,就会抛出Chart is not defined的错误。你在控制台看到script标签已存在,仅代表标签已插入DOM,不代表资源加载完成。
解决方案
你可以选择以下任意一种方式修复问题:
- 方案1:监听script加载完成事件,新增加载状态标记(避免重复加载、避免未加载完成时调用绘制逻辑)
修正后的代码如下:// 全局标记Chart.js加载状态 let chartJsReady = false; function add() { // 避免重复加载 if (chartJsReady) { console.log('Chart.js已加载完成,可直接绘制图表'); return; } const newScript = document.createElement("script"); newScript.src = "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"; // 加载成功回调 newScript.onload = () => { chartJsReady = true; console.log('Chart.js加载完成,现在可以绘制图表'); // 如需加载完成后自动绘制,可直接在这里调用draw() }; // 加载失败回调 newScript.onerror = () => { console.error('Chart.js加载失败,请检查网络或CDN地址有效性'); }; document.head.appendChild(newScript); } function draw() { // 绘制前先判断是否加载完成 if (!chartJsReady || !window.Chart) { alert('Chart.js尚未加载完成,请稍后再试'); return; } // 原有绘制逻辑保持不变 const ctx = document.getElementById('myChart').getContext('2d'); const myChart = new Chart(ctx, { type: 'bar', data: { labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'], datasets: [{ label: '# of Votes', data: [12, 19, 3, 5, 2, 3], backgroundColor: [ 'rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)', 'rgba(75, 192, 192, 0.2)', 'rgba(153, 102, 255, 0.2)', 'rgba(255, 159, 64, 0.2)' ], borderColor: [ 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)' ], borderWidth: 1 }] }, options: { scales: { y: { beginAtZero: true } } } }); } - 方案2:如果业务允许提前加载资源,直接将Chart.js的script标签写在HTML的
<body>标签末尾,页面加载时就会提前完成资源加载,后续调用draw函数不会出现找不到构造函数的问题。 - 方案3:将脚本加载逻辑封装为返回Promise的函数,调用时通过async/await等待加载完成后再执行绘制逻辑,更符合现代JS编码习惯。
内容的提问来源于stack exchange,提问作者Yves-Marie Ip
相关产品推荐
相关产品推荐

