Vue3/Vite加载外部UMD组件出现Promise循环链错误求助
Fix: Chaining Cycle Detected for Promise When Loading External UMD Components in Vue3 + Vite
Let me break down what's causing your error and how to fix it step by step.
Root Cause
The TypeError: Chaining cycle detected for promise happens because your code creates a Promise that ultimately resolves to itself. Here's why:
- You assign
window[name]to a new Promise - In the script's
loadhandler, you try to resolve that samewindow[name](which is still the Promise itself if your UMD component didn't properly overwrite it) - This creates a circular reference in the Promise chain, triggering the error
Also, I noticed your code is missing the line to create the script element (const script = document.createElement('script')) — that would cause an additional error, so I'll fix that too.
Corrected Code
Here's the revised externalComponent function that fixes the cycle and adds better error handling:
export default async function externalComponent(url) { // Extract component name from the UMD filename const name = url.split(`/`).reverse()[0].match(/^(.*?)\.umd/)[1]; // Return immediately if the component is already loaded (not a cached Promise) if (window[name] && typeof window[name] !== 'object') { return window[name]; } // Create a new script element (this was missing in your original code!) const script = document.createElement('script'); script.async = true; // Create a Promise to wait for the script to load and execute const loadPromise = new Promise((resolve, reject) => { script.addEventListener('load', () => { // Verify the component was actually mounted to window by the UMD script if (window[name]) { resolve(window[name]); } else { reject(new Error(`Component "${name}" not found on window after loading script`)); } }); script.addEventListener('error', () => { reject(new Error(`Failed to load external script: ${url}`)); }); }); // Cache the Promise to avoid duplicate script requests window[name] = loadPromise; // Trigger the script load script.src = url; document.head.appendChild(script); // Return the Promise that resolves to the actual component return loadPromise; }
Key Fixes & Improvements
- Avoids Promise Cycles: We resolve the actual component (mounted to
window[name]by the UMD script) instead of resolving the cached Promise itself. - Explicit Script Creation: Adds the missing script element initialization.
- Better Cache Checks: Ensures we only return the cached value if it's the actual component (not the pending Promise).
- Clearer Error Messages: Helps debug cases where the UMD script fails to load or doesn't expose the component correctly.
Additional Troubleshooting Tips
- Verify UMD Component Name: Make sure the
libraryNameconfigured in your UMD component's build tool (e.g., Vite/Webpack) exactly matches thenameextracted from the URL (including capitalization). If they don't match,window[name]will never be overwritten with the component. - Check Browser Console: After loading the script, run
window[name]directly in the browser console to confirm the component is mounted correctly. - Vue3 Compatibility: Ensure your UMD component is built for Vue3 — Vue2 components won't work correctly in Vue3 runtime.
内容的提问来源于stack exchange,提问作者Peter Siegel
相关产品推荐
相关产品推荐

