如何判断动态import('/some-url')失败源于未找到JavaScript模块?
如何区分动态import的错误类型:模块加载失败还是模块内部报错?
我的浏览器端JavaScript使用import('/some-url')动态导入模块时,有时会抛出错误,想区分两种错误场景:一种是浏览器无法在/some-url处获取到模块(加载阶段失败),另一种是模块成功加载后,内部代码执行抛出错误。
目前不同浏览器对于模块加载失败的错误提示没有统一规范:
- Chrome中错误信息为
Failed to fetch dynamically imported module: https://stackoverflow.com/some-url - Firefox中错误信息为
error loading dynamically imported module
有一种依赖错误文案的实现方式,但可靠性很低——浏览器厂商随时可能修改错误信息:
async function isJavaScriptModule(url) { try { await import(url); } catch (err) { if (isNetworkError(err)) { return false; } else { // 模块加载后内部报错,但本身是合法JS模块,返回true return true; } } return true; } function isNetworkError(err) { const messages = [ "Failed to fetch dynamically imported module", "error loading dynamically imported module", ]; return messages.some((msg) => err.message.includes(msg)); }
更可靠的判断方案
可以通过错误对象的标准化属性(而非文案)来区分,核心思路是利用加载阶段错误关联的DOMException:
- 模块加载失败(资源不存在、网络问题等)时,错误会关联标准化的
DOMException,其name属性对应具体错误类型(如NotFoundError、NetworkError) - 模块内部报错时,抛出的是代码执行产生的原生错误(如
Error、TypeError),不会携带加载相关的DOMException
具体实现代码:
async function isJavaScriptModule(url) { try { await import(url); return true; } catch (err) { // 判断是否为加载阶段的错误 const isLoadFailure = // Chrome场景:TypeError包裹,cause属性是DOMException (err instanceof TypeError && err.cause instanceof DOMException && ['NotFoundError', 'NetworkError'].includes(err.cause.name)) || // Firefox场景:直接抛出DOMException (err instanceof DOMException && ['NotFoundError', 'NetworkError'].includes(err.name)); if (isLoadFailure) { // 加载失败,非有效可加载的JS模块 return false; } else { // 模块加载成功但内部报错,属于有效JS模块 return true; } } }
补充说明:
DOMException的name属性是Web标准定义的,相比错误文案稳定性高很多- 部分浏览器会将加载错误包装在
TypeError中,但通过cause属性可以拿到底层的DOMException,这是ES规范的错误链机制,兼容性良好 - 模块内部抛出的错误不会带有这类加载相关的
DOMException,可以明确区分两种场景
内容的提问来源于stack exchange,提问作者brillout
相关产品推荐
相关产品推荐

