resource-preloader 2.0.3 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +4 -3
  2. package/dist/resource-loader.amd.js +4 -4
  3. package/dist/resource-loader.amd.js.map +1 -1
  4. package/dist/resource-loader.amd.min.js.map +1 -1
  5. package/dist/resource-loader.cjs.js +4 -4
  6. package/dist/resource-loader.cjs.js.map +1 -1
  7. package/dist/resource-loader.cjs.min.js.map +1 -1
  8. package/dist/resource-loader.esm.js +2 -2
  9. package/dist/resource-loader.esm.js.map +1 -1
  10. package/dist/resource-loader.esm.min.js +1 -1
  11. package/dist/resource-loader.esm.min.js.map +1 -1
  12. package/dist/resource-loader.umd.js +4 -4
  13. package/dist/resource-loader.umd.js.map +1 -1
  14. package/dist/resource-loader.umd.min.js.map +1 -1
  15. package/dist/resource-preloader.amd.js +130 -71
  16. package/dist/resource-preloader.amd.js.map +1 -1
  17. package/dist/resource-preloader.amd.min.js +1 -1
  18. package/dist/resource-preloader.amd.min.js.map +1 -1
  19. package/dist/resource-preloader.cjs.js +130 -71
  20. package/dist/resource-preloader.cjs.js.map +1 -1
  21. package/dist/resource-preloader.cjs.min.js +1 -1
  22. package/dist/resource-preloader.cjs.min.js.map +1 -1
  23. package/dist/resource-preloader.esm.js +130 -71
  24. package/dist/resource-preloader.esm.js.map +1 -1
  25. package/dist/resource-preloader.esm.min.js +1 -1
  26. package/dist/resource-preloader.esm.min.js.map +1 -1
  27. package/dist/resource-preloader.umd.js +130 -71
  28. package/dist/resource-preloader.umd.js.map +1 -1
  29. package/dist/resource-preloader.umd.min.js +1 -1
  30. package/dist/resource-preloader.umd.min.js.map +1 -1
  31. package/package.json +1 -1
  32. package/src/config.js +4 -3
  33. package/src/loader.js +109 -51
  34. package/src/scheduler.js +18 -21
  35. package/types/index.d.ts +2 -2
package/README.md CHANGED
@@ -1,15 +1,16 @@
1
1
  ## 资源加载器
2
2
 
3
- > 为了在vue项目中,预加载某些资源,开发此加载器
3
+ > 项目初衷: 为了在vue项目中,预加载某些资源,开发此加载器
4
4
  >
5
- > 在需要动态使用字体图标时,需要加载某全部的字体图标库。
5
+ > 需要动态使用字体图标时,需要加载某全部的字体图标库,然后将图标库类名存储到后端,显示时读取类名并设置实现动态图标。
6
6
  >
7
7
  > 加载时,想要先从CDN加载,如果失败,才从本地加载。
8
8
 
9
9
 
10
10
  ```js
11
11
  /** 加载器说明 **/
12
- // 预制了 css js 加载器
12
+ // 预制了 css js img json 加载器
13
+ // 结果类型:`Array<ResourceLoadResult>`
13
14
 
14
15
  /** 加载配置说明 **/
15
16
  const config = [
@@ -274,7 +274,7 @@ define((function () { 'use strict';
274
274
  * @param {Array<ResourceConfig>} configList - 输入配置数组
275
275
  * @returns {Promise<ResourceLoadResult[]>} 按配置定义顺序的加载结果数组
276
276
  */
277
- async function resourcePreloader(configList) {
277
+ async function preloadResources(configList) {
278
278
  if (!Array.isArray(configList) || configList.length === 0) {
279
279
  throw new Error('配置数组必须是非空数组');
280
280
  }
@@ -326,10 +326,10 @@ define((function () { 'use strict';
326
326
  });
327
327
  }
328
328
 
329
- resourcePreloader.registerLoader = registerLoader;
330
- resourcePreloader.setGlobalConfig = setGlobalConfig;
329
+ preloadResources.registerLoader = registerLoader;
330
+ preloadResources.setGlobalConfig = setGlobalConfig;
331
331
 
332
- return resourcePreloader;
332
+ return preloadResources;
333
333
 
334
334
  }));
335
335
  //# sourceMappingURL=resource-loader.amd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resource-loader.amd.js","sources":["../src/config.js","../src/loader.js","../src/scheduler.js","../src/other.js"],"sourcesContent":["// 默认公共配置\nconst defaultConfig = {\n timeout: 1000, // 默认超时时间1s\n retry: 0, // 默认不重试\n};\n\nlet globalConfig = { ...defaultConfig };\n\n/**\n * 配置公共配置的方法(导出)\n * @param {Object} config - 需覆盖的公共配置\n * @returns {Object} 合并后的最终全局配置\n */\nfunction setGlobalConfig(config) {\n if (typeof config !== 'object' || config === null) {\n throw new Error('配置参数必须是一个非空对象');\n }\n globalConfig = { ...globalConfig, ...config };\n return { ...globalConfig };\n}\n\n/**\n * 获取当前全局配置\n * @returns {Object} 全局配置\n */\nfunction getGlobalConfig() {\n return { ...globalConfig };\n}\n\nexport { setGlobalConfig, getGlobalConfig };","// 加载器映射表(存储内置+自定义加载器)\nconst loaderMap = new Map();\n\n/**\n * 通用资源加载Promise封装\n * @param {string} url - 资源地址\n * @param {Function} loadHandler - 具体的资源加载处理函数\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 加载结果Promise\n */\nfunction wrapLoadPromise(url, loadHandler, timeout) {\n return new Promise((resolve, reject) => {\n // 超时处理\n const timeoutTimer = setTimeout(() => {\n reject(new Error(`Resource ${url} load timeout (${timeout}ms)`));\n }, timeout);\n\n // 执行具体加载逻辑\n loadHandler(url)\n .then((result) => {\n clearTimeout(timeoutTimer);\n resolve({\n url,\n success: true,\n data: result,\n error: null,\n });\n })\n .catch((error) => {\n clearTimeout(timeoutTimer);\n reject({\n url,\n success: false,\n data: null,\n error,\n });\n });\n });\n}\n\n// --------------- 内置JS加载器 ---------------\nfunction jsLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.src = url;\n script.async = false; // 保持加载顺序(不开启异步)\n\n script.onload = () => {\n resolve(script);\n document.head.removeChild(script); // 可选:加载完成后移除标签,避免污染DOM\n };\n\n script.onerror = () => {\n reject(new Error(`JS resource ${url} load failed`));\n document.head.removeChild(script);\n };\n\n document.head.appendChild(script);\n });\n}\n\n// --------------- 内置CSS加载器 ---------------\nfunction cssLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n\n link.onload = () => {\n resolve(link);\n };\n\n link.onerror = () => {\n reject(new Error(`CSS resource ${url} load failed`));\n };\n\n document.head.appendChild(link);\n });\n}\n\n// 初始化内置加载器\nloaderMap.set('js', jsLoaderHandler);\nloaderMap.set('css', cssLoaderHandler);\n\n/**\n * 注册自定义加载器的方法(导出)\n * @param {string} type - 资源类型(唯一标识)\n * @param {Function} handler - 加载处理函数,接收url参数,返回Promise\n */\nfunction registerLoader(type, handler) {\n if (typeof type !== 'string' || type.trim() === '') {\n throw new Error('资源类型必须是非空字符串');\n }\n if (typeof handler !== 'function' || handler.constructor.name !== 'Function') {\n throw new Error('加载器必须是一个函数,且返回Promise对象');\n }\n if (loaderMap.has(type)) {\n console.warn(`类型为${type}的加载器已存在,将被覆盖`);\n }\n loaderMap.set(type, handler);\n}\n\n/**\n * 获取对应类型的加载器\n * @param {string} type - 资源类型\n * @returns {Function} 加载器处理函数\n */\nfunction getLoader(type) {\n if (!loaderMap.has(type)) {\n throw new Error(`未找到${type}类型的加载器,请先注册自定义加载器`);\n }\n return loaderMap.get(type);\n}\n\nexport { registerLoader, getLoader, wrapLoadPromise }; // 导出wrapLoadPromise,避免冗余","import {getGlobalConfig} from './config.js';\nimport {getLoader, wrapLoadPromise} from './loader.js';\n\n/**\n * 检测循环依赖(深度优先遍历,配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n * @param {number} currentId - 当前资源ID\n * @param {Set} visited - 已访问的资源ID集合\n * @param {Set} visiting - 正在访问的资源ID集合(用于检测环)\n */\nfunction detectCycle(configList, currentId, visited, visiting) {\n const currentConfig = configList.find(item => item.name === currentId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${currentId}的资源配置`);\n }\n\n // 若正在访问中,说明存在循环依赖\n if (visiting.has(currentId)) {\n throw new Error(`检测到循环依赖:${Array.from(visiting).join(' -> ')} -> ${currentId}`);\n }\n\n // 若已访问过,直接返回(无需重复检测)\n if (visited.has(currentId)) {\n return;\n }\n\n // 标记为正在访问\n visiting.add(currentId);\n // 递归检测依赖项(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n detectCycle(configList, depId, visited, visiting);\n }\n // 标记为已访问,移出正在访问集合\n visiting.delete(currentId);\n visited.add(currentId);\n}\n\n/**\n * 预检测所有资源的循环依赖(配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n */\nfunction checkAllCycles(configList) {\n const visited = new Set();\n for (const config of configList) {\n detectCycle(configList, config.name, visited, new Set());\n }\n}\n\n/**\n * 递归加载单个资源及其所有依赖(保证依赖先加载,配置字段改为dependencies)\n * @param {string|number} resourceId - 资源ID\n * @param {Array} configList - 完整配置数组\n * @param {number} timeout - 超时时间\n * @param {Map} loadedMap - 已加载资源的结果缓存\n */\nasync function loadResourceWithDeps(resourceId, configList, timeout, loadedMap) {\n // 若已加载,直接返回缓存结果\n if (loadedMap.has(resourceId)) {\n return loadedMap.get(resourceId);\n }\n\n const currentConfig = configList.find(item => item.name === resourceId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${resourceId}的资源配置`);\n }\n\n // 1. 先加载所有依赖(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n await loadResourceWithDeps(depId, configList, timeout, loadedMap);\n }\n\n // 2. 再加载当前资源的urls(顺序加载,一个成功即可)\n const {urls, type} = currentConfig;\n let loadResult = null;\n let status = 'success';\n let error = null;\n\n try {\n loadResult = await loadUrlsInOrder(urls, type, timeout);\n } catch (err) {\n status = 'failed';\n error = err;\n }\n\n // 3. 缓存加载结果\n const result = {\n resourceId,\n config: currentConfig,\n loadResult,\n status,\n error,\n };\n loadedMap.set(resourceId, result);\n return result;\n}\n\n/**\n * 按顺序加载urls,只需要一个成功即可\n * @param {Array} urls - 资源地址数组\n * @param {string} type - 资源类型\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 第一个成功的加载结果\n */\nasync function loadUrlsInOrder(urls, type, timeout) {\n if (!Array.isArray(urls) || urls.length === 0) {\n throw new Error('urls必须是非空数组');\n }\n\n const loader = getLoader(type);\n let lastError;\n\n // 按顺序遍历urls,直到有一个加载成功\n for (const url of urls) {\n try {\n return await wrapLoadPromise(url, loader, timeout);\n } catch (error) {\n lastError = error;\n continue; // 加载失败,继续下一个url\n }\n }\n\n // 所有url都加载失败,抛出最后一个错误\n throw new Error(`所有${type}类型资源加载失败,最后一个错误:${lastError?.message || '未知错误'}`);\n}\n\n/**\n * 核心加载调度方法(最终结果保持配置定义顺序)\n * @param {Array<ResourceConfig>} configList - 输入配置数组\n * @returns {Promise<ResourceLoadResult[]>} 按配置定义顺序的加载结果数组\n */\nasync function resourcePreloader(configList) {\n if (!Array.isArray(configList) || configList.length === 0) {\n throw new Error('配置数组必须是非空数组');\n }\n\n // 将 string[] 形式处理成 { name, urls, type } 形式\n configList = configList.map(item => {\n if (typeof item === 'string') {\n const url = new URL(item, window.location.href);\n return {\n name: url.pathname,\n urls: [item],\n type: url.pathname.split('.').pop() || 'js',\n };\n } else if (Array.isArray(item)) {\n if (!item.length) {\n return;\n }\n const url = new URL(item[0], window.location.href);\n return {\n name: url.pathname,\n urls: item,\n type: url.pathname.split('.').pop() || 'js',\n };\n } else {\n return item;\n }\n }).filter(Boolean);\n\n // 1. 获取全局配置\n const {timeout: globalTimeout} = getGlobalConfig();\n\n // 2. 预检测所有循环依赖(防止无限递归)\n checkAllCycles(configList);\n\n // 3. 初始化缓存(存储已加载资源结果,避免重复加载)\n const loadedMap = new Map();\n\n // 4. 按配置定义的顺序,并行加载同层级无依赖资源(保证依赖先加载,结果保留原始顺序)\n const rawOrderPromises = configList.map(async (config) => {\n return await loadResourceWithDeps(config.name, configList, globalTimeout, loadedMap);\n });\n\n // 5. 等待所有资源加载完成,返回原始配置顺序的结果\n return Promise.all(rawOrderPromises).then(function (result) {\n if (result.find(item => item.error)) {\n return Promise.reject(result);\n }\n return result;\n });\n}\n\nexport {resourcePreloader};","import {resourcePreloader} from \"./scheduler.js\";\nimport {registerLoader} from \"./loader.js\";\nimport {setGlobalConfig} from \"./config.js\";\n\nresourcePreloader.registerLoader = registerLoader;\nresourcePreloader.setGlobalConfig = setGlobalConfig;\n\nexport default resourcePreloader;"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resource-loader.amd.js","sources":["../src/config.js","../src/loader.js","../src/scheduler.js","../src/other.js"],"sourcesContent":["// 默认公共配置\nconst defaultConfig = {\n timeout: 1000, // 默认超时时间1s\n retry: 0, // 默认不重试\n};\n\nlet globalConfig = { ...defaultConfig };\n\n/**\n * 配置公共配置的方法(导出)\n * @param {Object} config - 需覆盖的公共配置\n * @returns {Object} 合并后的最终全局配置\n */\nfunction setGlobalConfig(config) {\n if (typeof config !== 'object' || config === null) {\n throw new Error('配置参数必须是一个非空对象');\n }\n globalConfig = { ...globalConfig, ...config };\n return { ...globalConfig };\n}\n\n/**\n * 获取当前全局配置\n * @returns {Object} 全局配置\n */\nfunction getGlobalConfig() {\n return { ...globalConfig };\n}\n\nexport { setGlobalConfig, getGlobalConfig };","// 加载器映射表(存储内置+自定义加载器)\nconst loaderMap = new Map();\n\n/**\n * 通用资源加载Promise封装\n * @param {string} url - 资源地址\n * @param {Function} loadHandler - 具体的资源加载处理函数\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 加载结果Promise\n */\nfunction wrapLoadPromise(url, loadHandler, timeout) {\n return new Promise((resolve, reject) => {\n // 超时处理\n const timeoutTimer = setTimeout(() => {\n reject(new Error(`Resource ${url} load timeout (${timeout}ms)`));\n }, timeout);\n\n // 执行具体加载逻辑\n loadHandler(url)\n .then((result) => {\n clearTimeout(timeoutTimer);\n resolve({\n url,\n success: true,\n data: result,\n error: null,\n });\n })\n .catch((error) => {\n clearTimeout(timeoutTimer);\n reject({\n url,\n success: false,\n data: null,\n error,\n });\n });\n });\n}\n\n// --------------- 内置JS加载器 ---------------\nfunction jsLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.src = url;\n script.async = false; // 保持加载顺序(不开启异步)\n\n script.onload = () => {\n resolve(script);\n document.head.removeChild(script); // 可选:加载完成后移除标签,避免污染DOM\n };\n\n script.onerror = () => {\n reject(new Error(`JS resource ${url} load failed`));\n document.head.removeChild(script);\n };\n\n document.head.appendChild(script);\n });\n}\n\n// --------------- 内置CSS加载器 ---------------\nfunction cssLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n\n link.onload = () => {\n resolve(link);\n };\n\n link.onerror = () => {\n reject(new Error(`CSS resource ${url} load failed`));\n };\n\n document.head.appendChild(link);\n });\n}\n\n// 初始化内置加载器\nloaderMap.set('js', jsLoaderHandler);\nloaderMap.set('css', cssLoaderHandler);\n\n/**\n * 注册自定义加载器的方法(导出)\n * @param {string} type - 资源类型(唯一标识)\n * @param {Function} handler - 加载处理函数,接收url参数,返回Promise\n */\nfunction registerLoader(type, handler) {\n if (typeof type !== 'string' || type.trim() === '') {\n throw new Error('资源类型必须是非空字符串');\n }\n if (typeof handler !== 'function' || handler.constructor.name !== 'Function') {\n throw new Error('加载器必须是一个函数,且返回Promise对象');\n }\n if (loaderMap.has(type)) {\n console.warn(`类型为${type}的加载器已存在,将被覆盖`);\n }\n loaderMap.set(type, handler);\n}\n\n/**\n * 获取对应类型的加载器\n * @param {string} type - 资源类型\n * @returns {Function} 加载器处理函数\n */\nfunction getLoader(type) {\n if (!loaderMap.has(type)) {\n throw new Error(`未找到${type}类型的加载器,请先注册自定义加载器`);\n }\n return loaderMap.get(type);\n}\n\nexport { registerLoader, getLoader, wrapLoadPromise }; // 导出wrapLoadPromise,避免冗余","import {getGlobalConfig} from './config.js';\nimport {getLoader, wrapLoadPromise} from './loader.js';\n\n/**\n * 检测循环依赖(深度优先遍历,配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n * @param {number} currentId - 当前资源ID\n * @param {Set} visited - 已访问的资源ID集合\n * @param {Set} visiting - 正在访问的资源ID集合(用于检测环)\n */\nfunction detectCycle(configList, currentId, visited, visiting) {\n const currentConfig = configList.find(item => item.name === currentId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${currentId}的资源配置`);\n }\n\n // 若正在访问中,说明存在循环依赖\n if (visiting.has(currentId)) {\n throw new Error(`检测到循环依赖:${Array.from(visiting).join(' -> ')} -> ${currentId}`);\n }\n\n // 若已访问过,直接返回(无需重复检测)\n if (visited.has(currentId)) {\n return;\n }\n\n // 标记为正在访问\n visiting.add(currentId);\n // 递归检测依赖项(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n detectCycle(configList, depId, visited, visiting);\n }\n // 标记为已访问,移出正在访问集合\n visiting.delete(currentId);\n visited.add(currentId);\n}\n\n/**\n * 预检测所有资源的循环依赖(配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n */\nfunction checkAllCycles(configList) {\n const visited = new Set();\n for (const config of configList) {\n detectCycle(configList, config.name, visited, new Set());\n }\n}\n\n/**\n * 递归加载单个资源及其所有依赖(保证依赖先加载,配置字段改为dependencies)\n * @param {string|number} resourceId - 资源ID\n * @param {Array} configList - 完整配置数组\n * @param {number} timeout - 超时时间\n * @param {Map} loadedMap - 已加载资源的结果缓存\n */\nasync function loadResourceWithDeps(resourceId, configList, timeout, loadedMap) {\n // 若已加载,直接返回缓存结果\n if (loadedMap.has(resourceId)) {\n return loadedMap.get(resourceId);\n }\n\n const currentConfig = configList.find(item => item.name === resourceId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${resourceId}的资源配置`);\n }\n\n // 1. 先加载所有依赖(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n await loadResourceWithDeps(depId, configList, timeout, loadedMap);\n }\n\n // 2. 再加载当前资源的urls(顺序加载,一个成功即可)\n const {urls, type} = currentConfig;\n let loadResult = null;\n let status = 'success';\n let error = null;\n\n try {\n loadResult = await loadUrlsInOrder(urls, type, timeout);\n } catch (err) {\n status = 'failed';\n error = err;\n }\n\n // 3. 缓存加载结果\n const result = {\n resourceId,\n config: currentConfig,\n loadResult,\n status,\n error,\n };\n loadedMap.set(resourceId, result);\n return result;\n}\n\n/**\n * 按顺序加载urls,只需要一个成功即可\n * @param {Array} urls - 资源地址数组\n * @param {string} type - 资源类型\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 第一个成功的加载结果\n */\nasync function loadUrlsInOrder(urls, type, timeout) {\n if (!Array.isArray(urls) || urls.length === 0) {\n throw new Error('urls必须是非空数组');\n }\n\n const loader = getLoader(type);\n let lastError;\n\n // 按顺序遍历urls,直到有一个加载成功\n for (const url of urls) {\n try {\n return await wrapLoadPromise(url, loader, timeout);\n } catch (error) {\n lastError = error;\n continue; // 加载失败,继续下一个url\n }\n }\n\n // 所有url都加载失败,抛出最后一个错误\n throw new Error(`所有${type}类型资源加载失败,最后一个错误:${lastError?.message || '未知错误'}`);\n}\n\n/**\n * 核心加载调度方法(最终结果保持配置定义顺序)\n * @param {Array<ResourceConfig>} configList - 输入配置数组\n * @returns {Promise<ResourceLoadResult[]>} 按配置定义顺序的加载结果数组\n */\nasync function preloadResources(configList) {\n if (!Array.isArray(configList) || configList.length === 0) {\n throw new Error('配置数组必须是非空数组');\n }\n\n // 将 string[] 形式处理成 { name, urls, type } 形式\n configList = configList.map(item => {\n if (typeof item === 'string') {\n const url = new URL(item, window.location.href);\n return {\n name: url.pathname,\n urls: [item],\n type: url.pathname.split('.').pop() || 'js',\n };\n } else if (Array.isArray(item)) {\n if (!item.length) {\n return;\n }\n const url = new URL(item[0], window.location.href);\n return {\n name: url.pathname,\n urls: item,\n type: url.pathname.split('.').pop() || 'js',\n };\n } else {\n return item;\n }\n }).filter(Boolean);\n\n // 1. 获取全局配置\n const {timeout: globalTimeout} = getGlobalConfig();\n\n // 2. 预检测所有循环依赖(防止无限递归)\n checkAllCycles(configList);\n\n // 3. 初始化缓存(存储已加载资源结果,避免重复加载)\n const loadedMap = new Map();\n\n // 4. 按配置定义的顺序,并行加载同层级无依赖资源(保证依赖先加载,结果保留原始顺序)\n const rawOrderPromises = configList.map(async (config) => {\n return await loadResourceWithDeps(config.name, configList, globalTimeout, loadedMap);\n });\n\n // 5. 等待所有资源加载完成,返回原始配置顺序的结果\n return Promise.all(rawOrderPromises).then(function (result) {\n if (result.find(item => item.error)) {\n return Promise.reject(result);\n }\n return result;\n });\n}\n\nexport {preloadResources};","import {preloadResources} from \"./scheduler.js\";\nimport {registerLoader} from \"./loader.js\";\nimport {setGlobalConfig} from \"./config.js\";\n\npreloadResources.registerLoader = registerLoader;\npreloadResources.setGlobalConfig = setGlobalConfig;\n\nexport default preloadResources;"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"resource-loader.amd.min.js","sources":["../src/config.js","../src/loader.js","../src/scheduler.js","../src/other.js"],"sourcesContent":["// 默认公共配置\nconst defaultConfig = {\n timeout: 1000, // 默认超时时间1s\n retry: 0, // 默认不重试\n};\n\nlet globalConfig = { ...defaultConfig };\n\n/**\n * 配置公共配置的方法(导出)\n * @param {Object} config - 需覆盖的公共配置\n * @returns {Object} 合并后的最终全局配置\n */\nfunction setGlobalConfig(config) {\n if (typeof config !== 'object' || config === null) {\n throw new Error('配置参数必须是一个非空对象');\n }\n globalConfig = { ...globalConfig, ...config };\n return { ...globalConfig };\n}\n\n/**\n * 获取当前全局配置\n * @returns {Object} 全局配置\n */\nfunction getGlobalConfig() {\n return { ...globalConfig };\n}\n\nexport { setGlobalConfig, getGlobalConfig };","// 加载器映射表(存储内置+自定义加载器)\nconst loaderMap = new Map();\n\n/**\n * 通用资源加载Promise封装\n * @param {string} url - 资源地址\n * @param {Function} loadHandler - 具体的资源加载处理函数\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 加载结果Promise\n */\nfunction wrapLoadPromise(url, loadHandler, timeout) {\n return new Promise((resolve, reject) => {\n // 超时处理\n const timeoutTimer = setTimeout(() => {\n reject(new Error(`Resource ${url} load timeout (${timeout}ms)`));\n }, timeout);\n\n // 执行具体加载逻辑\n loadHandler(url)\n .then((result) => {\n clearTimeout(timeoutTimer);\n resolve({\n url,\n success: true,\n data: result,\n error: null,\n });\n })\n .catch((error) => {\n clearTimeout(timeoutTimer);\n reject({\n url,\n success: false,\n data: null,\n error,\n });\n });\n });\n}\n\n// --------------- 内置JS加载器 ---------------\nfunction jsLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.src = url;\n script.async = false; // 保持加载顺序(不开启异步)\n\n script.onload = () => {\n resolve(script);\n document.head.removeChild(script); // 可选:加载完成后移除标签,避免污染DOM\n };\n\n script.onerror = () => {\n reject(new Error(`JS resource ${url} load failed`));\n document.head.removeChild(script);\n };\n\n document.head.appendChild(script);\n });\n}\n\n// --------------- 内置CSS加载器 ---------------\nfunction cssLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n\n link.onload = () => {\n resolve(link);\n };\n\n link.onerror = () => {\n reject(new Error(`CSS resource ${url} load failed`));\n };\n\n document.head.appendChild(link);\n });\n}\n\n// 初始化内置加载器\nloaderMap.set('js', jsLoaderHandler);\nloaderMap.set('css', cssLoaderHandler);\n\n/**\n * 注册自定义加载器的方法(导出)\n * @param {string} type - 资源类型(唯一标识)\n * @param {Function} handler - 加载处理函数,接收url参数,返回Promise\n */\nfunction registerLoader(type, handler) {\n if (typeof type !== 'string' || type.trim() === '') {\n throw new Error('资源类型必须是非空字符串');\n }\n if (typeof handler !== 'function' || handler.constructor.name !== 'Function') {\n throw new Error('加载器必须是一个函数,且返回Promise对象');\n }\n if (loaderMap.has(type)) {\n console.warn(`类型为${type}的加载器已存在,将被覆盖`);\n }\n loaderMap.set(type, handler);\n}\n\n/**\n * 获取对应类型的加载器\n * @param {string} type - 资源类型\n * @returns {Function} 加载器处理函数\n */\nfunction getLoader(type) {\n if (!loaderMap.has(type)) {\n throw new Error(`未找到${type}类型的加载器,请先注册自定义加载器`);\n }\n return loaderMap.get(type);\n}\n\nexport { registerLoader, getLoader, wrapLoadPromise }; // 导出wrapLoadPromise,避免冗余","import {getGlobalConfig} from './config.js';\nimport {getLoader, wrapLoadPromise} from './loader.js';\n\n/**\n * 检测循环依赖(深度优先遍历,配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n * @param {number} currentId - 当前资源ID\n * @param {Set} visited - 已访问的资源ID集合\n * @param {Set} visiting - 正在访问的资源ID集合(用于检测环)\n */\nfunction detectCycle(configList, currentId, visited, visiting) {\n const currentConfig = configList.find(item => item.name === currentId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${currentId}的资源配置`);\n }\n\n // 若正在访问中,说明存在循环依赖\n if (visiting.has(currentId)) {\n throw new Error(`检测到循环依赖:${Array.from(visiting).join(' -> ')} -> ${currentId}`);\n }\n\n // 若已访问过,直接返回(无需重复检测)\n if (visited.has(currentId)) {\n return;\n }\n\n // 标记为正在访问\n visiting.add(currentId);\n // 递归检测依赖项(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n detectCycle(configList, depId, visited, visiting);\n }\n // 标记为已访问,移出正在访问集合\n visiting.delete(currentId);\n visited.add(currentId);\n}\n\n/**\n * 预检测所有资源的循环依赖(配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n */\nfunction checkAllCycles(configList) {\n const visited = new Set();\n for (const config of configList) {\n detectCycle(configList, config.name, visited, new Set());\n }\n}\n\n/**\n * 递归加载单个资源及其所有依赖(保证依赖先加载,配置字段改为dependencies)\n * @param {string|number} resourceId - 资源ID\n * @param {Array} configList - 完整配置数组\n * @param {number} timeout - 超时时间\n * @param {Map} loadedMap - 已加载资源的结果缓存\n */\nasync function loadResourceWithDeps(resourceId, configList, timeout, loadedMap) {\n // 若已加载,直接返回缓存结果\n if (loadedMap.has(resourceId)) {\n return loadedMap.get(resourceId);\n }\n\n const currentConfig = configList.find(item => item.name === resourceId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${resourceId}的资源配置`);\n }\n\n // 1. 先加载所有依赖(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n await loadResourceWithDeps(depId, configList, timeout, loadedMap);\n }\n\n // 2. 再加载当前资源的urls(顺序加载,一个成功即可)\n const {urls, type} = currentConfig;\n let loadResult = null;\n let status = 'success';\n let error = null;\n\n try {\n loadResult = await loadUrlsInOrder(urls, type, timeout);\n } catch (err) {\n status = 'failed';\n error = err;\n }\n\n // 3. 缓存加载结果\n const result = {\n resourceId,\n config: currentConfig,\n loadResult,\n status,\n error,\n };\n loadedMap.set(resourceId, result);\n return result;\n}\n\n/**\n * 按顺序加载urls,只需要一个成功即可\n * @param {Array} urls - 资源地址数组\n * @param {string} type - 资源类型\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 第一个成功的加载结果\n */\nasync function loadUrlsInOrder(urls, type, timeout) {\n if (!Array.isArray(urls) || urls.length === 0) {\n throw new Error('urls必须是非空数组');\n }\n\n const loader = getLoader(type);\n let lastError;\n\n // 按顺序遍历urls,直到有一个加载成功\n for (const url of urls) {\n try {\n return await wrapLoadPromise(url, loader, timeout);\n } catch (error) {\n lastError = error;\n continue; // 加载失败,继续下一个url\n }\n }\n\n // 所有url都加载失败,抛出最后一个错误\n throw new Error(`所有${type}类型资源加载失败,最后一个错误:${lastError?.message || '未知错误'}`);\n}\n\n/**\n * 核心加载调度方法(最终结果保持配置定义顺序)\n * @param {Array<ResourceConfig>} configList - 输入配置数组\n * @returns {Promise<ResourceLoadResult[]>} 按配置定义顺序的加载结果数组\n */\nasync function resourcePreloader(configList) {\n if (!Array.isArray(configList) || configList.length === 0) {\n throw new Error('配置数组必须是非空数组');\n }\n\n // 将 string[] 形式处理成 { name, urls, type } 形式\n configList = configList.map(item => {\n if (typeof item === 'string') {\n const url = new URL(item, window.location.href);\n return {\n name: url.pathname,\n urls: [item],\n type: url.pathname.split('.').pop() || 'js',\n };\n } else if (Array.isArray(item)) {\n if (!item.length) {\n return;\n }\n const url = new URL(item[0], window.location.href);\n return {\n name: url.pathname,\n urls: item,\n type: url.pathname.split('.').pop() || 'js',\n };\n } else {\n return item;\n }\n }).filter(Boolean);\n\n // 1. 获取全局配置\n const {timeout: globalTimeout} = getGlobalConfig();\n\n // 2. 预检测所有循环依赖(防止无限递归)\n checkAllCycles(configList);\n\n // 3. 初始化缓存(存储已加载资源结果,避免重复加载)\n const loadedMap = new Map();\n\n // 4. 按配置定义的顺序,并行加载同层级无依赖资源(保证依赖先加载,结果保留原始顺序)\n const rawOrderPromises = configList.map(async (config) => {\n return await loadResourceWithDeps(config.name, configList, globalTimeout, loadedMap);\n });\n\n // 5. 等待所有资源加载完成,返回原始配置顺序的结果\n return Promise.all(rawOrderPromises).then(function (result) {\n if (result.find(item => item.error)) {\n return Promise.reject(result);\n }\n return result;\n });\n}\n\nexport {resourcePreloader};","import {resourcePreloader} from \"./scheduler.js\";\nimport {registerLoader} from \"./loader.js\";\nimport {setGlobalConfig} from \"./config.js\";\n\nresourcePreloader.registerLoader = registerLoader;\nresourcePreloader.setGlobalConfig = setGlobalConfig;\n\nexport default resourcePreloader;"],"names":["globalConfig","timeout","retry","loaderMap","Map","wrapLoadPromise","url","loadHandler","Promise","resolve","reject","timeoutTimer","setTimeout","Error","then","result","clearTimeout","success","data","error","catch","detectCycle","configList","currentId","visited","visiting","currentConfig","find","item","name","has","Array","from","join","add","dependencies","depId","delete","async","loadResourceWithDeps","resourceId","loadedMap","get","urls","type","loadResult","status","isArray","length","loader","getLoader","lastError","message","loadUrlsInOrder","err","config","set","resourcePreloader","map","URL","window","location","href","pathname","split","pop","filter","Boolean","globalTimeout","Set","checkAllCycles","rawOrderPromises","all","script","document","createElement","src","onload","head","removeChild","onerror","appendChild","link","rel","registerLoader","handler","trim","constructor","console","warn","setGlobalConfig"],"mappings":"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"}
1
+ {"version":3,"file":"resource-loader.amd.min.js","sources":["../src/config.js","../src/loader.js","../src/scheduler.js","../src/other.js"],"sourcesContent":["// 默认公共配置\nconst defaultConfig = {\n timeout: 1000, // 默认超时时间1s\n retry: 0, // 默认不重试\n};\n\nlet globalConfig = { ...defaultConfig };\n\n/**\n * 配置公共配置的方法(导出)\n * @param {Object} config - 需覆盖的公共配置\n * @returns {Object} 合并后的最终全局配置\n */\nfunction setGlobalConfig(config) {\n if (typeof config !== 'object' || config === null) {\n throw new Error('配置参数必须是一个非空对象');\n }\n globalConfig = { ...globalConfig, ...config };\n return { ...globalConfig };\n}\n\n/**\n * 获取当前全局配置\n * @returns {Object} 全局配置\n */\nfunction getGlobalConfig() {\n return { ...globalConfig };\n}\n\nexport { setGlobalConfig, getGlobalConfig };","// 加载器映射表(存储内置+自定义加载器)\nconst loaderMap = new Map();\n\n/**\n * 通用资源加载Promise封装\n * @param {string} url - 资源地址\n * @param {Function} loadHandler - 具体的资源加载处理函数\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 加载结果Promise\n */\nfunction wrapLoadPromise(url, loadHandler, timeout) {\n return new Promise((resolve, reject) => {\n // 超时处理\n const timeoutTimer = setTimeout(() => {\n reject(new Error(`Resource ${url} load timeout (${timeout}ms)`));\n }, timeout);\n\n // 执行具体加载逻辑\n loadHandler(url)\n .then((result) => {\n clearTimeout(timeoutTimer);\n resolve({\n url,\n success: true,\n data: result,\n error: null,\n });\n })\n .catch((error) => {\n clearTimeout(timeoutTimer);\n reject({\n url,\n success: false,\n data: null,\n error,\n });\n });\n });\n}\n\n// --------------- 内置JS加载器 ---------------\nfunction jsLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.src = url;\n script.async = false; // 保持加载顺序(不开启异步)\n\n script.onload = () => {\n resolve(script);\n document.head.removeChild(script); // 可选:加载完成后移除标签,避免污染DOM\n };\n\n script.onerror = () => {\n reject(new Error(`JS resource ${url} load failed`));\n document.head.removeChild(script);\n };\n\n document.head.appendChild(script);\n });\n}\n\n// --------------- 内置CSS加载器 ---------------\nfunction cssLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n\n link.onload = () => {\n resolve(link);\n };\n\n link.onerror = () => {\n reject(new Error(`CSS resource ${url} load failed`));\n };\n\n document.head.appendChild(link);\n });\n}\n\n// 初始化内置加载器\nloaderMap.set('js', jsLoaderHandler);\nloaderMap.set('css', cssLoaderHandler);\n\n/**\n * 注册自定义加载器的方法(导出)\n * @param {string} type - 资源类型(唯一标识)\n * @param {Function} handler - 加载处理函数,接收url参数,返回Promise\n */\nfunction registerLoader(type, handler) {\n if (typeof type !== 'string' || type.trim() === '') {\n throw new Error('资源类型必须是非空字符串');\n }\n if (typeof handler !== 'function' || handler.constructor.name !== 'Function') {\n throw new Error('加载器必须是一个函数,且返回Promise对象');\n }\n if (loaderMap.has(type)) {\n console.warn(`类型为${type}的加载器已存在,将被覆盖`);\n }\n loaderMap.set(type, handler);\n}\n\n/**\n * 获取对应类型的加载器\n * @param {string} type - 资源类型\n * @returns {Function} 加载器处理函数\n */\nfunction getLoader(type) {\n if (!loaderMap.has(type)) {\n throw new Error(`未找到${type}类型的加载器,请先注册自定义加载器`);\n }\n return loaderMap.get(type);\n}\n\nexport { registerLoader, getLoader, wrapLoadPromise }; // 导出wrapLoadPromise,避免冗余","import {getGlobalConfig} from './config.js';\nimport {getLoader, wrapLoadPromise} from './loader.js';\n\n/**\n * 检测循环依赖(深度优先遍历,配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n * @param {number} currentId - 当前资源ID\n * @param {Set} visited - 已访问的资源ID集合\n * @param {Set} visiting - 正在访问的资源ID集合(用于检测环)\n */\nfunction detectCycle(configList, currentId, visited, visiting) {\n const currentConfig = configList.find(item => item.name === currentId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${currentId}的资源配置`);\n }\n\n // 若正在访问中,说明存在循环依赖\n if (visiting.has(currentId)) {\n throw new Error(`检测到循环依赖:${Array.from(visiting).join(' -> ')} -> ${currentId}`);\n }\n\n // 若已访问过,直接返回(无需重复检测)\n if (visited.has(currentId)) {\n return;\n }\n\n // 标记为正在访问\n visiting.add(currentId);\n // 递归检测依赖项(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n detectCycle(configList, depId, visited, visiting);\n }\n // 标记为已访问,移出正在访问集合\n visiting.delete(currentId);\n visited.add(currentId);\n}\n\n/**\n * 预检测所有资源的循环依赖(配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n */\nfunction checkAllCycles(configList) {\n const visited = new Set();\n for (const config of configList) {\n detectCycle(configList, config.name, visited, new Set());\n }\n}\n\n/**\n * 递归加载单个资源及其所有依赖(保证依赖先加载,配置字段改为dependencies)\n * @param {string|number} resourceId - 资源ID\n * @param {Array} configList - 完整配置数组\n * @param {number} timeout - 超时时间\n * @param {Map} loadedMap - 已加载资源的结果缓存\n */\nasync function loadResourceWithDeps(resourceId, configList, timeout, loadedMap) {\n // 若已加载,直接返回缓存结果\n if (loadedMap.has(resourceId)) {\n return loadedMap.get(resourceId);\n }\n\n const currentConfig = configList.find(item => item.name === resourceId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${resourceId}的资源配置`);\n }\n\n // 1. 先加载所有依赖(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n await loadResourceWithDeps(depId, configList, timeout, loadedMap);\n }\n\n // 2. 再加载当前资源的urls(顺序加载,一个成功即可)\n const {urls, type} = currentConfig;\n let loadResult = null;\n let status = 'success';\n let error = null;\n\n try {\n loadResult = await loadUrlsInOrder(urls, type, timeout);\n } catch (err) {\n status = 'failed';\n error = err;\n }\n\n // 3. 缓存加载结果\n const result = {\n resourceId,\n config: currentConfig,\n loadResult,\n status,\n error,\n };\n loadedMap.set(resourceId, result);\n return result;\n}\n\n/**\n * 按顺序加载urls,只需要一个成功即可\n * @param {Array} urls - 资源地址数组\n * @param {string} type - 资源类型\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 第一个成功的加载结果\n */\nasync function loadUrlsInOrder(urls, type, timeout) {\n if (!Array.isArray(urls) || urls.length === 0) {\n throw new Error('urls必须是非空数组');\n }\n\n const loader = getLoader(type);\n let lastError;\n\n // 按顺序遍历urls,直到有一个加载成功\n for (const url of urls) {\n try {\n return await wrapLoadPromise(url, loader, timeout);\n } catch (error) {\n lastError = error;\n continue; // 加载失败,继续下一个url\n }\n }\n\n // 所有url都加载失败,抛出最后一个错误\n throw new Error(`所有${type}类型资源加载失败,最后一个错误:${lastError?.message || '未知错误'}`);\n}\n\n/**\n * 核心加载调度方法(最终结果保持配置定义顺序)\n * @param {Array<ResourceConfig>} configList - 输入配置数组\n * @returns {Promise<ResourceLoadResult[]>} 按配置定义顺序的加载结果数组\n */\nasync function preloadResources(configList) {\n if (!Array.isArray(configList) || configList.length === 0) {\n throw new Error('配置数组必须是非空数组');\n }\n\n // 将 string[] 形式处理成 { name, urls, type } 形式\n configList = configList.map(item => {\n if (typeof item === 'string') {\n const url = new URL(item, window.location.href);\n return {\n name: url.pathname,\n urls: [item],\n type: url.pathname.split('.').pop() || 'js',\n };\n } else if (Array.isArray(item)) {\n if (!item.length) {\n return;\n }\n const url = new URL(item[0], window.location.href);\n return {\n name: url.pathname,\n urls: item,\n type: url.pathname.split('.').pop() || 'js',\n };\n } else {\n return item;\n }\n }).filter(Boolean);\n\n // 1. 获取全局配置\n const {timeout: globalTimeout} = getGlobalConfig();\n\n // 2. 预检测所有循环依赖(防止无限递归)\n checkAllCycles(configList);\n\n // 3. 初始化缓存(存储已加载资源结果,避免重复加载)\n const loadedMap = new Map();\n\n // 4. 按配置定义的顺序,并行加载同层级无依赖资源(保证依赖先加载,结果保留原始顺序)\n const rawOrderPromises = configList.map(async (config) => {\n return await loadResourceWithDeps(config.name, configList, globalTimeout, loadedMap);\n });\n\n // 5. 等待所有资源加载完成,返回原始配置顺序的结果\n return Promise.all(rawOrderPromises).then(function (result) {\n if (result.find(item => item.error)) {\n return Promise.reject(result);\n }\n return result;\n });\n}\n\nexport {preloadResources};","import {preloadResources} from \"./scheduler.js\";\nimport {registerLoader} from \"./loader.js\";\nimport {setGlobalConfig} from \"./config.js\";\n\npreloadResources.registerLoader = registerLoader;\npreloadResources.setGlobalConfig = setGlobalConfig;\n\nexport default preloadResources;"],"names":["globalConfig","timeout","retry","loaderMap","Map","wrapLoadPromise","url","loadHandler","Promise","resolve","reject","timeoutTimer","setTimeout","Error","then","result","clearTimeout","success","data","error","catch","detectCycle","configList","currentId","visited","visiting","currentConfig","find","item","name","has","Array","from","join","add","dependencies","depId","delete","async","loadResourceWithDeps","resourceId","loadedMap","get","urls","type","loadResult","status","isArray","length","loader","getLoader","lastError","message","loadUrlsInOrder","err","config","set","preloadResources","map","URL","window","location","href","pathname","split","pop","filter","Boolean","globalTimeout","Set","checkAllCycles","rawOrderPromises","all","script","document","createElement","src","onload","head","removeChild","onerror","appendChild","link","rel","registerLoader","handler","trim","constructor","console","warn","setGlobalConfig"],"mappings":"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"}
@@ -274,7 +274,7 @@ async function loadUrlsInOrder(urls, type, timeout) {
274
274
  * @param {Array<ResourceConfig>} configList - 输入配置数组
275
275
  * @returns {Promise<ResourceLoadResult[]>} 按配置定义顺序的加载结果数组
276
276
  */
277
- async function resourcePreloader(configList) {
277
+ async function preloadResources(configList) {
278
278
  if (!Array.isArray(configList) || configList.length === 0) {
279
279
  throw new Error('配置数组必须是非空数组');
280
280
  }
@@ -326,8 +326,8 @@ async function resourcePreloader(configList) {
326
326
  });
327
327
  }
328
328
 
329
- resourcePreloader.registerLoader = registerLoader;
330
- resourcePreloader.setGlobalConfig = setGlobalConfig;
329
+ preloadResources.registerLoader = registerLoader;
330
+ preloadResources.setGlobalConfig = setGlobalConfig;
331
331
 
332
- module.exports = resourcePreloader;
332
+ module.exports = preloadResources;
333
333
  //# sourceMappingURL=resource-loader.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resource-loader.cjs.js","sources":["../src/config.js","../src/loader.js","../src/scheduler.js","../src/other.js"],"sourcesContent":["// 默认公共配置\nconst defaultConfig = {\n timeout: 1000, // 默认超时时间1s\n retry: 0, // 默认不重试\n};\n\nlet globalConfig = { ...defaultConfig };\n\n/**\n * 配置公共配置的方法(导出)\n * @param {Object} config - 需覆盖的公共配置\n * @returns {Object} 合并后的最终全局配置\n */\nfunction setGlobalConfig(config) {\n if (typeof config !== 'object' || config === null) {\n throw new Error('配置参数必须是一个非空对象');\n }\n globalConfig = { ...globalConfig, ...config };\n return { ...globalConfig };\n}\n\n/**\n * 获取当前全局配置\n * @returns {Object} 全局配置\n */\nfunction getGlobalConfig() {\n return { ...globalConfig };\n}\n\nexport { setGlobalConfig, getGlobalConfig };","// 加载器映射表(存储内置+自定义加载器)\nconst loaderMap = new Map();\n\n/**\n * 通用资源加载Promise封装\n * @param {string} url - 资源地址\n * @param {Function} loadHandler - 具体的资源加载处理函数\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 加载结果Promise\n */\nfunction wrapLoadPromise(url, loadHandler, timeout) {\n return new Promise((resolve, reject) => {\n // 超时处理\n const timeoutTimer = setTimeout(() => {\n reject(new Error(`Resource ${url} load timeout (${timeout}ms)`));\n }, timeout);\n\n // 执行具体加载逻辑\n loadHandler(url)\n .then((result) => {\n clearTimeout(timeoutTimer);\n resolve({\n url,\n success: true,\n data: result,\n error: null,\n });\n })\n .catch((error) => {\n clearTimeout(timeoutTimer);\n reject({\n url,\n success: false,\n data: null,\n error,\n });\n });\n });\n}\n\n// --------------- 内置JS加载器 ---------------\nfunction jsLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.src = url;\n script.async = false; // 保持加载顺序(不开启异步)\n\n script.onload = () => {\n resolve(script);\n document.head.removeChild(script); // 可选:加载完成后移除标签,避免污染DOM\n };\n\n script.onerror = () => {\n reject(new Error(`JS resource ${url} load failed`));\n document.head.removeChild(script);\n };\n\n document.head.appendChild(script);\n });\n}\n\n// --------------- 内置CSS加载器 ---------------\nfunction cssLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n\n link.onload = () => {\n resolve(link);\n };\n\n link.onerror = () => {\n reject(new Error(`CSS resource ${url} load failed`));\n };\n\n document.head.appendChild(link);\n });\n}\n\n// 初始化内置加载器\nloaderMap.set('js', jsLoaderHandler);\nloaderMap.set('css', cssLoaderHandler);\n\n/**\n * 注册自定义加载器的方法(导出)\n * @param {string} type - 资源类型(唯一标识)\n * @param {Function} handler - 加载处理函数,接收url参数,返回Promise\n */\nfunction registerLoader(type, handler) {\n if (typeof type !== 'string' || type.trim() === '') {\n throw new Error('资源类型必须是非空字符串');\n }\n if (typeof handler !== 'function' || handler.constructor.name !== 'Function') {\n throw new Error('加载器必须是一个函数,且返回Promise对象');\n }\n if (loaderMap.has(type)) {\n console.warn(`类型为${type}的加载器已存在,将被覆盖`);\n }\n loaderMap.set(type, handler);\n}\n\n/**\n * 获取对应类型的加载器\n * @param {string} type - 资源类型\n * @returns {Function} 加载器处理函数\n */\nfunction getLoader(type) {\n if (!loaderMap.has(type)) {\n throw new Error(`未找到${type}类型的加载器,请先注册自定义加载器`);\n }\n return loaderMap.get(type);\n}\n\nexport { registerLoader, getLoader, wrapLoadPromise }; // 导出wrapLoadPromise,避免冗余","import {getGlobalConfig} from './config.js';\nimport {getLoader, wrapLoadPromise} from './loader.js';\n\n/**\n * 检测循环依赖(深度优先遍历,配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n * @param {number} currentId - 当前资源ID\n * @param {Set} visited - 已访问的资源ID集合\n * @param {Set} visiting - 正在访问的资源ID集合(用于检测环)\n */\nfunction detectCycle(configList, currentId, visited, visiting) {\n const currentConfig = configList.find(item => item.name === currentId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${currentId}的资源配置`);\n }\n\n // 若正在访问中,说明存在循环依赖\n if (visiting.has(currentId)) {\n throw new Error(`检测到循环依赖:${Array.from(visiting).join(' -> ')} -> ${currentId}`);\n }\n\n // 若已访问过,直接返回(无需重复检测)\n if (visited.has(currentId)) {\n return;\n }\n\n // 标记为正在访问\n visiting.add(currentId);\n // 递归检测依赖项(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n detectCycle(configList, depId, visited, visiting);\n }\n // 标记为已访问,移出正在访问集合\n visiting.delete(currentId);\n visited.add(currentId);\n}\n\n/**\n * 预检测所有资源的循环依赖(配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n */\nfunction checkAllCycles(configList) {\n const visited = new Set();\n for (const config of configList) {\n detectCycle(configList, config.name, visited, new Set());\n }\n}\n\n/**\n * 递归加载单个资源及其所有依赖(保证依赖先加载,配置字段改为dependencies)\n * @param {string|number} resourceId - 资源ID\n * @param {Array} configList - 完整配置数组\n * @param {number} timeout - 超时时间\n * @param {Map} loadedMap - 已加载资源的结果缓存\n */\nasync function loadResourceWithDeps(resourceId, configList, timeout, loadedMap) {\n // 若已加载,直接返回缓存结果\n if (loadedMap.has(resourceId)) {\n return loadedMap.get(resourceId);\n }\n\n const currentConfig = configList.find(item => item.name === resourceId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${resourceId}的资源配置`);\n }\n\n // 1. 先加载所有依赖(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n await loadResourceWithDeps(depId, configList, timeout, loadedMap);\n }\n\n // 2. 再加载当前资源的urls(顺序加载,一个成功即可)\n const {urls, type} = currentConfig;\n let loadResult = null;\n let status = 'success';\n let error = null;\n\n try {\n loadResult = await loadUrlsInOrder(urls, type, timeout);\n } catch (err) {\n status = 'failed';\n error = err;\n }\n\n // 3. 缓存加载结果\n const result = {\n resourceId,\n config: currentConfig,\n loadResult,\n status,\n error,\n };\n loadedMap.set(resourceId, result);\n return result;\n}\n\n/**\n * 按顺序加载urls,只需要一个成功即可\n * @param {Array} urls - 资源地址数组\n * @param {string} type - 资源类型\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 第一个成功的加载结果\n */\nasync function loadUrlsInOrder(urls, type, timeout) {\n if (!Array.isArray(urls) || urls.length === 0) {\n throw new Error('urls必须是非空数组');\n }\n\n const loader = getLoader(type);\n let lastError;\n\n // 按顺序遍历urls,直到有一个加载成功\n for (const url of urls) {\n try {\n return await wrapLoadPromise(url, loader, timeout);\n } catch (error) {\n lastError = error;\n continue; // 加载失败,继续下一个url\n }\n }\n\n // 所有url都加载失败,抛出最后一个错误\n throw new Error(`所有${type}类型资源加载失败,最后一个错误:${lastError?.message || '未知错误'}`);\n}\n\n/**\n * 核心加载调度方法(最终结果保持配置定义顺序)\n * @param {Array<ResourceConfig>} configList - 输入配置数组\n * @returns {Promise<ResourceLoadResult[]>} 按配置定义顺序的加载结果数组\n */\nasync function resourcePreloader(configList) {\n if (!Array.isArray(configList) || configList.length === 0) {\n throw new Error('配置数组必须是非空数组');\n }\n\n // 将 string[] 形式处理成 { name, urls, type } 形式\n configList = configList.map(item => {\n if (typeof item === 'string') {\n const url = new URL(item, window.location.href);\n return {\n name: url.pathname,\n urls: [item],\n type: url.pathname.split('.').pop() || 'js',\n };\n } else if (Array.isArray(item)) {\n if (!item.length) {\n return;\n }\n const url = new URL(item[0], window.location.href);\n return {\n name: url.pathname,\n urls: item,\n type: url.pathname.split('.').pop() || 'js',\n };\n } else {\n return item;\n }\n }).filter(Boolean);\n\n // 1. 获取全局配置\n const {timeout: globalTimeout} = getGlobalConfig();\n\n // 2. 预检测所有循环依赖(防止无限递归)\n checkAllCycles(configList);\n\n // 3. 初始化缓存(存储已加载资源结果,避免重复加载)\n const loadedMap = new Map();\n\n // 4. 按配置定义的顺序,并行加载同层级无依赖资源(保证依赖先加载,结果保留原始顺序)\n const rawOrderPromises = configList.map(async (config) => {\n return await loadResourceWithDeps(config.name, configList, globalTimeout, loadedMap);\n });\n\n // 5. 等待所有资源加载完成,返回原始配置顺序的结果\n return Promise.all(rawOrderPromises).then(function (result) {\n if (result.find(item => item.error)) {\n return Promise.reject(result);\n }\n return result;\n });\n}\n\nexport {resourcePreloader};","import {resourcePreloader} from \"./scheduler.js\";\nimport {registerLoader} from \"./loader.js\";\nimport {setGlobalConfig} from \"./config.js\";\n\nresourcePreloader.registerLoader = registerLoader;\nresourcePreloader.setGlobalConfig = setGlobalConfig;\n\nexport default resourcePreloader;"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resource-loader.cjs.js","sources":["../src/config.js","../src/loader.js","../src/scheduler.js","../src/other.js"],"sourcesContent":["// 默认公共配置\nconst defaultConfig = {\n timeout: 1000, // 默认超时时间1s\n retry: 0, // 默认不重试\n};\n\nlet globalConfig = { ...defaultConfig };\n\n/**\n * 配置公共配置的方法(导出)\n * @param {Object} config - 需覆盖的公共配置\n * @returns {Object} 合并后的最终全局配置\n */\nfunction setGlobalConfig(config) {\n if (typeof config !== 'object' || config === null) {\n throw new Error('配置参数必须是一个非空对象');\n }\n globalConfig = { ...globalConfig, ...config };\n return { ...globalConfig };\n}\n\n/**\n * 获取当前全局配置\n * @returns {Object} 全局配置\n */\nfunction getGlobalConfig() {\n return { ...globalConfig };\n}\n\nexport { setGlobalConfig, getGlobalConfig };","// 加载器映射表(存储内置+自定义加载器)\nconst loaderMap = new Map();\n\n/**\n * 通用资源加载Promise封装\n * @param {string} url - 资源地址\n * @param {Function} loadHandler - 具体的资源加载处理函数\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 加载结果Promise\n */\nfunction wrapLoadPromise(url, loadHandler, timeout) {\n return new Promise((resolve, reject) => {\n // 超时处理\n const timeoutTimer = setTimeout(() => {\n reject(new Error(`Resource ${url} load timeout (${timeout}ms)`));\n }, timeout);\n\n // 执行具体加载逻辑\n loadHandler(url)\n .then((result) => {\n clearTimeout(timeoutTimer);\n resolve({\n url,\n success: true,\n data: result,\n error: null,\n });\n })\n .catch((error) => {\n clearTimeout(timeoutTimer);\n reject({\n url,\n success: false,\n data: null,\n error,\n });\n });\n });\n}\n\n// --------------- 内置JS加载器 ---------------\nfunction jsLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.src = url;\n script.async = false; // 保持加载顺序(不开启异步)\n\n script.onload = () => {\n resolve(script);\n document.head.removeChild(script); // 可选:加载完成后移除标签,避免污染DOM\n };\n\n script.onerror = () => {\n reject(new Error(`JS resource ${url} load failed`));\n document.head.removeChild(script);\n };\n\n document.head.appendChild(script);\n });\n}\n\n// --------------- 内置CSS加载器 ---------------\nfunction cssLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n\n link.onload = () => {\n resolve(link);\n };\n\n link.onerror = () => {\n reject(new Error(`CSS resource ${url} load failed`));\n };\n\n document.head.appendChild(link);\n });\n}\n\n// 初始化内置加载器\nloaderMap.set('js', jsLoaderHandler);\nloaderMap.set('css', cssLoaderHandler);\n\n/**\n * 注册自定义加载器的方法(导出)\n * @param {string} type - 资源类型(唯一标识)\n * @param {Function} handler - 加载处理函数,接收url参数,返回Promise\n */\nfunction registerLoader(type, handler) {\n if (typeof type !== 'string' || type.trim() === '') {\n throw new Error('资源类型必须是非空字符串');\n }\n if (typeof handler !== 'function' || handler.constructor.name !== 'Function') {\n throw new Error('加载器必须是一个函数,且返回Promise对象');\n }\n if (loaderMap.has(type)) {\n console.warn(`类型为${type}的加载器已存在,将被覆盖`);\n }\n loaderMap.set(type, handler);\n}\n\n/**\n * 获取对应类型的加载器\n * @param {string} type - 资源类型\n * @returns {Function} 加载器处理函数\n */\nfunction getLoader(type) {\n if (!loaderMap.has(type)) {\n throw new Error(`未找到${type}类型的加载器,请先注册自定义加载器`);\n }\n return loaderMap.get(type);\n}\n\nexport { registerLoader, getLoader, wrapLoadPromise }; // 导出wrapLoadPromise,避免冗余","import {getGlobalConfig} from './config.js';\nimport {getLoader, wrapLoadPromise} from './loader.js';\n\n/**\n * 检测循环依赖(深度优先遍历,配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n * @param {number} currentId - 当前资源ID\n * @param {Set} visited - 已访问的资源ID集合\n * @param {Set} visiting - 正在访问的资源ID集合(用于检测环)\n */\nfunction detectCycle(configList, currentId, visited, visiting) {\n const currentConfig = configList.find(item => item.name === currentId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${currentId}的资源配置`);\n }\n\n // 若正在访问中,说明存在循环依赖\n if (visiting.has(currentId)) {\n throw new Error(`检测到循环依赖:${Array.from(visiting).join(' -> ')} -> ${currentId}`);\n }\n\n // 若已访问过,直接返回(无需重复检测)\n if (visited.has(currentId)) {\n return;\n }\n\n // 标记为正在访问\n visiting.add(currentId);\n // 递归检测依赖项(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n detectCycle(configList, depId, visited, visiting);\n }\n // 标记为已访问,移出正在访问集合\n visiting.delete(currentId);\n visited.add(currentId);\n}\n\n/**\n * 预检测所有资源的循环依赖(配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n */\nfunction checkAllCycles(configList) {\n const visited = new Set();\n for (const config of configList) {\n detectCycle(configList, config.name, visited, new Set());\n }\n}\n\n/**\n * 递归加载单个资源及其所有依赖(保证依赖先加载,配置字段改为dependencies)\n * @param {string|number} resourceId - 资源ID\n * @param {Array} configList - 完整配置数组\n * @param {number} timeout - 超时时间\n * @param {Map} loadedMap - 已加载资源的结果缓存\n */\nasync function loadResourceWithDeps(resourceId, configList, timeout, loadedMap) {\n // 若已加载,直接返回缓存结果\n if (loadedMap.has(resourceId)) {\n return loadedMap.get(resourceId);\n }\n\n const currentConfig = configList.find(item => item.name === resourceId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${resourceId}的资源配置`);\n }\n\n // 1. 先加载所有依赖(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n await loadResourceWithDeps(depId, configList, timeout, loadedMap);\n }\n\n // 2. 再加载当前资源的urls(顺序加载,一个成功即可)\n const {urls, type} = currentConfig;\n let loadResult = null;\n let status = 'success';\n let error = null;\n\n try {\n loadResult = await loadUrlsInOrder(urls, type, timeout);\n } catch (err) {\n status = 'failed';\n error = err;\n }\n\n // 3. 缓存加载结果\n const result = {\n resourceId,\n config: currentConfig,\n loadResult,\n status,\n error,\n };\n loadedMap.set(resourceId, result);\n return result;\n}\n\n/**\n * 按顺序加载urls,只需要一个成功即可\n * @param {Array} urls - 资源地址数组\n * @param {string} type - 资源类型\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 第一个成功的加载结果\n */\nasync function loadUrlsInOrder(urls, type, timeout) {\n if (!Array.isArray(urls) || urls.length === 0) {\n throw new Error('urls必须是非空数组');\n }\n\n const loader = getLoader(type);\n let lastError;\n\n // 按顺序遍历urls,直到有一个加载成功\n for (const url of urls) {\n try {\n return await wrapLoadPromise(url, loader, timeout);\n } catch (error) {\n lastError = error;\n continue; // 加载失败,继续下一个url\n }\n }\n\n // 所有url都加载失败,抛出最后一个错误\n throw new Error(`所有${type}类型资源加载失败,最后一个错误:${lastError?.message || '未知错误'}`);\n}\n\n/**\n * 核心加载调度方法(最终结果保持配置定义顺序)\n * @param {Array<ResourceConfig>} configList - 输入配置数组\n * @returns {Promise<ResourceLoadResult[]>} 按配置定义顺序的加载结果数组\n */\nasync function preloadResources(configList) {\n if (!Array.isArray(configList) || configList.length === 0) {\n throw new Error('配置数组必须是非空数组');\n }\n\n // 将 string[] 形式处理成 { name, urls, type } 形式\n configList = configList.map(item => {\n if (typeof item === 'string') {\n const url = new URL(item, window.location.href);\n return {\n name: url.pathname,\n urls: [item],\n type: url.pathname.split('.').pop() || 'js',\n };\n } else if (Array.isArray(item)) {\n if (!item.length) {\n return;\n }\n const url = new URL(item[0], window.location.href);\n return {\n name: url.pathname,\n urls: item,\n type: url.pathname.split('.').pop() || 'js',\n };\n } else {\n return item;\n }\n }).filter(Boolean);\n\n // 1. 获取全局配置\n const {timeout: globalTimeout} = getGlobalConfig();\n\n // 2. 预检测所有循环依赖(防止无限递归)\n checkAllCycles(configList);\n\n // 3. 初始化缓存(存储已加载资源结果,避免重复加载)\n const loadedMap = new Map();\n\n // 4. 按配置定义的顺序,并行加载同层级无依赖资源(保证依赖先加载,结果保留原始顺序)\n const rawOrderPromises = configList.map(async (config) => {\n return await loadResourceWithDeps(config.name, configList, globalTimeout, loadedMap);\n });\n\n // 5. 等待所有资源加载完成,返回原始配置顺序的结果\n return Promise.all(rawOrderPromises).then(function (result) {\n if (result.find(item => item.error)) {\n return Promise.reject(result);\n }\n return result;\n });\n}\n\nexport {preloadResources};","import {preloadResources} from \"./scheduler.js\";\nimport {registerLoader} from \"./loader.js\";\nimport {setGlobalConfig} from \"./config.js\";\n\npreloadResources.registerLoader = registerLoader;\npreloadResources.setGlobalConfig = setGlobalConfig;\n\nexport default preloadResources;"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"resource-loader.cjs.min.js","sources":["../src/config.js","../src/loader.js","../src/scheduler.js","../src/other.js"],"sourcesContent":["// 默认公共配置\nconst defaultConfig = {\n timeout: 1000, // 默认超时时间1s\n retry: 0, // 默认不重试\n};\n\nlet globalConfig = { ...defaultConfig };\n\n/**\n * 配置公共配置的方法(导出)\n * @param {Object} config - 需覆盖的公共配置\n * @returns {Object} 合并后的最终全局配置\n */\nfunction setGlobalConfig(config) {\n if (typeof config !== 'object' || config === null) {\n throw new Error('配置参数必须是一个非空对象');\n }\n globalConfig = { ...globalConfig, ...config };\n return { ...globalConfig };\n}\n\n/**\n * 获取当前全局配置\n * @returns {Object} 全局配置\n */\nfunction getGlobalConfig() {\n return { ...globalConfig };\n}\n\nexport { setGlobalConfig, getGlobalConfig };","// 加载器映射表(存储内置+自定义加载器)\nconst loaderMap = new Map();\n\n/**\n * 通用资源加载Promise封装\n * @param {string} url - 资源地址\n * @param {Function} loadHandler - 具体的资源加载处理函数\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 加载结果Promise\n */\nfunction wrapLoadPromise(url, loadHandler, timeout) {\n return new Promise((resolve, reject) => {\n // 超时处理\n const timeoutTimer = setTimeout(() => {\n reject(new Error(`Resource ${url} load timeout (${timeout}ms)`));\n }, timeout);\n\n // 执行具体加载逻辑\n loadHandler(url)\n .then((result) => {\n clearTimeout(timeoutTimer);\n resolve({\n url,\n success: true,\n data: result,\n error: null,\n });\n })\n .catch((error) => {\n clearTimeout(timeoutTimer);\n reject({\n url,\n success: false,\n data: null,\n error,\n });\n });\n });\n}\n\n// --------------- 内置JS加载器 ---------------\nfunction jsLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.src = url;\n script.async = false; // 保持加载顺序(不开启异步)\n\n script.onload = () => {\n resolve(script);\n document.head.removeChild(script); // 可选:加载完成后移除标签,避免污染DOM\n };\n\n script.onerror = () => {\n reject(new Error(`JS resource ${url} load failed`));\n document.head.removeChild(script);\n };\n\n document.head.appendChild(script);\n });\n}\n\n// --------------- 内置CSS加载器 ---------------\nfunction cssLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n\n link.onload = () => {\n resolve(link);\n };\n\n link.onerror = () => {\n reject(new Error(`CSS resource ${url} load failed`));\n };\n\n document.head.appendChild(link);\n });\n}\n\n// 初始化内置加载器\nloaderMap.set('js', jsLoaderHandler);\nloaderMap.set('css', cssLoaderHandler);\n\n/**\n * 注册自定义加载器的方法(导出)\n * @param {string} type - 资源类型(唯一标识)\n * @param {Function} handler - 加载处理函数,接收url参数,返回Promise\n */\nfunction registerLoader(type, handler) {\n if (typeof type !== 'string' || type.trim() === '') {\n throw new Error('资源类型必须是非空字符串');\n }\n if (typeof handler !== 'function' || handler.constructor.name !== 'Function') {\n throw new Error('加载器必须是一个函数,且返回Promise对象');\n }\n if (loaderMap.has(type)) {\n console.warn(`类型为${type}的加载器已存在,将被覆盖`);\n }\n loaderMap.set(type, handler);\n}\n\n/**\n * 获取对应类型的加载器\n * @param {string} type - 资源类型\n * @returns {Function} 加载器处理函数\n */\nfunction getLoader(type) {\n if (!loaderMap.has(type)) {\n throw new Error(`未找到${type}类型的加载器,请先注册自定义加载器`);\n }\n return loaderMap.get(type);\n}\n\nexport { registerLoader, getLoader, wrapLoadPromise }; // 导出wrapLoadPromise,避免冗余","import {getGlobalConfig} from './config.js';\nimport {getLoader, wrapLoadPromise} from './loader.js';\n\n/**\n * 检测循环依赖(深度优先遍历,配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n * @param {number} currentId - 当前资源ID\n * @param {Set} visited - 已访问的资源ID集合\n * @param {Set} visiting - 正在访问的资源ID集合(用于检测环)\n */\nfunction detectCycle(configList, currentId, visited, visiting) {\n const currentConfig = configList.find(item => item.name === currentId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${currentId}的资源配置`);\n }\n\n // 若正在访问中,说明存在循环依赖\n if (visiting.has(currentId)) {\n throw new Error(`检测到循环依赖:${Array.from(visiting).join(' -> ')} -> ${currentId}`);\n }\n\n // 若已访问过,直接返回(无需重复检测)\n if (visited.has(currentId)) {\n return;\n }\n\n // 标记为正在访问\n visiting.add(currentId);\n // 递归检测依赖项(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n detectCycle(configList, depId, visited, visiting);\n }\n // 标记为已访问,移出正在访问集合\n visiting.delete(currentId);\n visited.add(currentId);\n}\n\n/**\n * 预检测所有资源的循环依赖(配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n */\nfunction checkAllCycles(configList) {\n const visited = new Set();\n for (const config of configList) {\n detectCycle(configList, config.name, visited, new Set());\n }\n}\n\n/**\n * 递归加载单个资源及其所有依赖(保证依赖先加载,配置字段改为dependencies)\n * @param {string|number} resourceId - 资源ID\n * @param {Array} configList - 完整配置数组\n * @param {number} timeout - 超时时间\n * @param {Map} loadedMap - 已加载资源的结果缓存\n */\nasync function loadResourceWithDeps(resourceId, configList, timeout, loadedMap) {\n // 若已加载,直接返回缓存结果\n if (loadedMap.has(resourceId)) {\n return loadedMap.get(resourceId);\n }\n\n const currentConfig = configList.find(item => item.name === resourceId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${resourceId}的资源配置`);\n }\n\n // 1. 先加载所有依赖(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n await loadResourceWithDeps(depId, configList, timeout, loadedMap);\n }\n\n // 2. 再加载当前资源的urls(顺序加载,一个成功即可)\n const {urls, type} = currentConfig;\n let loadResult = null;\n let status = 'success';\n let error = null;\n\n try {\n loadResult = await loadUrlsInOrder(urls, type, timeout);\n } catch (err) {\n status = 'failed';\n error = err;\n }\n\n // 3. 缓存加载结果\n const result = {\n resourceId,\n config: currentConfig,\n loadResult,\n status,\n error,\n };\n loadedMap.set(resourceId, result);\n return result;\n}\n\n/**\n * 按顺序加载urls,只需要一个成功即可\n * @param {Array} urls - 资源地址数组\n * @param {string} type - 资源类型\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 第一个成功的加载结果\n */\nasync function loadUrlsInOrder(urls, type, timeout) {\n if (!Array.isArray(urls) || urls.length === 0) {\n throw new Error('urls必须是非空数组');\n }\n\n const loader = getLoader(type);\n let lastError;\n\n // 按顺序遍历urls,直到有一个加载成功\n for (const url of urls) {\n try {\n return await wrapLoadPromise(url, loader, timeout);\n } catch (error) {\n lastError = error;\n continue; // 加载失败,继续下一个url\n }\n }\n\n // 所有url都加载失败,抛出最后一个错误\n throw new Error(`所有${type}类型资源加载失败,最后一个错误:${lastError?.message || '未知错误'}`);\n}\n\n/**\n * 核心加载调度方法(最终结果保持配置定义顺序)\n * @param {Array<ResourceConfig>} configList - 输入配置数组\n * @returns {Promise<ResourceLoadResult[]>} 按配置定义顺序的加载结果数组\n */\nasync function resourcePreloader(configList) {\n if (!Array.isArray(configList) || configList.length === 0) {\n throw new Error('配置数组必须是非空数组');\n }\n\n // 将 string[] 形式处理成 { name, urls, type } 形式\n configList = configList.map(item => {\n if (typeof item === 'string') {\n const url = new URL(item, window.location.href);\n return {\n name: url.pathname,\n urls: [item],\n type: url.pathname.split('.').pop() || 'js',\n };\n } else if (Array.isArray(item)) {\n if (!item.length) {\n return;\n }\n const url = new URL(item[0], window.location.href);\n return {\n name: url.pathname,\n urls: item,\n type: url.pathname.split('.').pop() || 'js',\n };\n } else {\n return item;\n }\n }).filter(Boolean);\n\n // 1. 获取全局配置\n const {timeout: globalTimeout} = getGlobalConfig();\n\n // 2. 预检测所有循环依赖(防止无限递归)\n checkAllCycles(configList);\n\n // 3. 初始化缓存(存储已加载资源结果,避免重复加载)\n const loadedMap = new Map();\n\n // 4. 按配置定义的顺序,并行加载同层级无依赖资源(保证依赖先加载,结果保留原始顺序)\n const rawOrderPromises = configList.map(async (config) => {\n return await loadResourceWithDeps(config.name, configList, globalTimeout, loadedMap);\n });\n\n // 5. 等待所有资源加载完成,返回原始配置顺序的结果\n return Promise.all(rawOrderPromises).then(function (result) {\n if (result.find(item => item.error)) {\n return Promise.reject(result);\n }\n return result;\n });\n}\n\nexport {resourcePreloader};","import {resourcePreloader} from \"./scheduler.js\";\nimport {registerLoader} from \"./loader.js\";\nimport {setGlobalConfig} from \"./config.js\";\n\nresourcePreloader.registerLoader = registerLoader;\nresourcePreloader.setGlobalConfig = setGlobalConfig;\n\nexport default resourcePreloader;"],"names":["globalConfig","timeout","retry","loaderMap","Map","wrapLoadPromise","url","loadHandler","Promise","resolve","reject","timeoutTimer","setTimeout","Error","then","result","clearTimeout","success","data","error","catch","detectCycle","configList","currentId","visited","visiting","currentConfig","find","item","name","has","Array","from","join","add","dependencies","depId","delete","async","loadResourceWithDeps","resourceId","loadedMap","get","urls","type","loadResult","status","isArray","length","loader","getLoader","lastError","message","loadUrlsInOrder","err","config","set","resourcePreloader","map","URL","window","location","href","pathname","split","pop","filter","Boolean","globalTimeout","Set","checkAllCycles","rawOrderPromises","all","script","document","createElement","src","onload","head","removeChild","onerror","appendChild","link","rel","registerLoader","handler","trim","constructor","console","warn","setGlobalConfig"],"mappings":"aAMA,IAAIA,EAAe,CAJfC,QAAS,IACTC,MAAO,GCFX,MAAMC,EAAY,IAAIC,IAStB,SAASC,EAAgBC,EAAKC,EAAaN,GACvC,OAAO,IAAIO,QAAQ,CAACC,EAASC,KAEzB,MAAMC,EAAeC,WAAW,KAC5BF,EAAO,IAAIG,MAAM,YAAYP,mBAAqBL,UACnDA,GAGHM,EAAYD,GACPQ,KAAMC,IACHC,aAAaL,GACbF,EAAQ,CACJH,MACAW,SAAS,EACTC,KAAMH,EACNI,MAAO,SAGdC,MAAOD,IACJH,aAAaL,GACbD,EAAO,CACHJ,MACAW,SAAS,EACTC,KAAM,KACNC,aAIpB,CC5BA,SAASE,EAAYC,EAAYC,EAAWC,EAASC,GACjD,MAAMC,EAAgBJ,EAAWK,KAAKC,GAAQA,EAAKC,OAASN,GAC5D,IAAKG,EACD,MAAM,IAAIb,MAAM,SAASU,UAI7B,GAAIE,EAASK,IAAIP,GACb,MAAM,IAAIV,MAAM,WAAWkB,MAAMC,KAAKP,GAAUQ,KAAK,cAAcV,KAIvE,GAAIC,EAAQM,IAAIP,GACZ,OAIJE,EAASS,IAAIX,GAEb,MAAMY,EAAeT,EAAcS,cAAgB,GACnD,IAAK,MAAMC,KAASD,EAChBd,EAAYC,EAAYc,EAAOZ,EAASC,GAG5CA,EAASY,OAAOd,GAChBC,EAAQU,IAAIX,EAChB,CAoBAe,eAAeC,EAAqBC,EAAYlB,EAAYrB,EAASwC,GAEjE,GAAIA,EAAUX,IAAIU,GACd,OAAOC,EAAUC,IAAIF,GAGzB,MAAMd,EAAgBJ,EAAWK,KAAKC,GAAQA,EAAKC,OAASW,GAC5D,IAAKd,EACD,MAAM,IAAIb,MAAM,SAAS2B,UAI7B,MAAML,EAAeT,EAAcS,cAAgB,GACnD,IAAK,MAAMC,KAASD,QACVI,EAAqBH,EAAOd,EAAYrB,EAASwC,GAI3D,MAAME,KAACA,EAAIC,KAAEA,GAAQlB,EACrB,IAAImB,EAAa,KACbC,EAAS,UACT3B,EAAQ,KAEZ,IACI0B,QAyBRP,eAA+BK,EAAMC,EAAM3C,GACvC,IAAK8B,MAAMgB,QAAQJ,IAAyB,IAAhBA,EAAKK,OAC7B,MAAM,IAAInC,MAAM,eAGpB,MAAMoC,EDFV,SAAmBL,GACf,IAAKzC,EAAU2B,IAAIc,GACf,MAAM,IAAI/B,MAAM,MAAM+B,sBAE1B,OAAOzC,EAAUuC,IAAIE,EACzB,CCHmBM,CAAUN,GACzB,IAAIO,EAGJ,IAAK,MAAM7C,KAAOqC,EACd,IACI,aAAatC,EAAgBC,EAAK2C,EAAQhD,EAC9C,CAAE,MAAOkB,GACLgC,EAAYhC,EACZ,QACJ,CAIJ,MAAM,IAAIN,MAAM,KAAK+B,oBAAuBO,GAAWC,SAAW,SACtE,CA7C2BC,CAAgBV,EAAMC,EAAM3C,EACnD,CAAE,MAAOqD,GACLR,EAAS,SACT3B,EAAQmC,CACZ,CAGA,MAAMvC,EAAS,CACXyB,aACAe,OAAQ7B,EACRmB,aACAC,SACA3B,SAGJ,OADAsB,EAAUe,IAAIhB,EAAYzB,GACnBA,CACX,CAoCAuB,eAAemB,EAAkBnC,GAC7B,IAAKS,MAAMgB,QAAQzB,IAAqC,IAAtBA,EAAW0B,OACzC,MAAM,IAAInC,MAAM,eAIpBS,EAAaA,EAAWoC,IAAI9B,IACxB,GAAoB,iBAATA,EAAmB,CAC1B,MAAMtB,EAAM,IAAIqD,IAAI/B,EAAMgC,OAAOC,SAASC,MAC1C,MAAO,CACHjC,KAAMvB,EAAIyD,SACVpB,KAAM,CAACf,GACPgB,KAAMtC,EAAIyD,SAASC,MAAM,KAAKC,OAAS,KAE/C,CAAO,GAAIlC,MAAMgB,QAAQnB,GAAO,CAC5B,IAAKA,EAAKoB,OACN,OAEJ,MAAM1C,EAAM,IAAIqD,IAAI/B,EAAK,GAAIgC,OAAOC,SAASC,MAC7C,MAAO,CACHjC,KAAMvB,EAAIyD,SACVpB,KAAMf,EACNgB,KAAMtC,EAAIyD,SAASC,MAAM,KAAKC,OAAS,KAE/C,CACI,OAAOrC,IAEZsC,OAAOC,SAGV,MAAOlE,QAASmE,GFxIT,IAAKpE,IEgBhB,SAAwBsB,GACpB,MAAME,EAAU,IAAI6C,IACpB,IAAK,MAAMd,KAAUjC,EACjBD,EAAYC,EAAYiC,EAAO1B,KAAML,EAAS,IAAI6C,IAE1D,CAsHIC,CAAehD,GAGf,MAAMmB,EAAY,IAAIrC,IAGhBmE,EAAmBjD,EAAWoC,IAAIpB,MAAOiB,SAC9BhB,EAAqBgB,EAAO1B,KAAMP,EAAY8C,EAAe3B,IAI9E,OAAOjC,QAAQgE,IAAID,GAAkBzD,KAAK,SAAUC,GAChD,OAAIA,EAAOY,KAAKC,GAAQA,EAAKT,OAClBX,QAAQE,OAAOK,GAEnBA,CACX,EACJ,CDpGAZ,EAAUqD,IAAI,KAzCd,SAAyBlD,GACrB,OAAO,IAAIE,QAAQ,CAACC,EAASC,KACzB,MAAM+D,EAASC,SAASC,cAAc,UACtCF,EAAO7B,KAAO,kBACd6B,EAAOG,IAAMtE,EACbmE,EAAOnC,OAAQ,EAEfmC,EAAOI,OAAS,KACZpE,EAAQgE,GACRC,SAASI,KAAKC,YAAYN,IAG9BA,EAAOO,QAAU,KACbtE,EAAO,IAAIG,MAAM,eAAeP,kBAChCoE,SAASI,KAAKC,YAAYN,IAG9BC,SAASI,KAAKG,YAAYR,IAElC,GAuBAtE,EAAUqD,IAAI,MApBd,SAA0BlD,GACtB,OAAO,IAAIE,QAAQ,CAACC,EAASC,KACzB,MAAMwE,EAAOR,SAASC,cAAc,QACpCO,EAAKC,IAAM,aACXD,EAAKpB,KAAOxD,EAEZ4E,EAAKL,OAAS,KACVpE,EAAQyE,IAGZA,EAAKF,QAAU,KACXtE,EAAO,IAAIG,MAAM,gBAAgBP,mBAGrCoE,SAASI,KAAKG,YAAYC,IAElC,GE3EAzB,EAAkB2B,eFsFlB,SAAwBxC,EAAMyC,GAC1B,GAAoB,iBAATzC,GAAqC,KAAhBA,EAAK0C,OACjC,MAAM,IAAIzE,MAAM,gBAEpB,GAAuB,mBAAZwE,GAAuD,aAA7BA,EAAQE,YAAY1D,KACrD,MAAM,IAAIhB,MAAM,2BAEhBV,EAAU2B,IAAIc,IACd4C,QAAQC,KAAK,MAAM7C,iBAEvBzC,EAAUqD,IAAIZ,EAAMyC,EACxB,EEhGA5B,EAAkBiC,gBHQlB,SAAyBnC,GACrB,GAAsB,iBAAXA,GAAkC,OAAXA,EAC9B,MAAM,IAAI1C,MAAM,iBAGpB,OADAb,EAAe,IAAKA,KAAiBuD,GAC9B,IAAKvD,EAChB"}
1
+ {"version":3,"file":"resource-loader.cjs.min.js","sources":["../src/config.js","../src/loader.js","../src/scheduler.js","../src/other.js"],"sourcesContent":["// 默认公共配置\nconst defaultConfig = {\n timeout: 1000, // 默认超时时间1s\n retry: 0, // 默认不重试\n};\n\nlet globalConfig = { ...defaultConfig };\n\n/**\n * 配置公共配置的方法(导出)\n * @param {Object} config - 需覆盖的公共配置\n * @returns {Object} 合并后的最终全局配置\n */\nfunction setGlobalConfig(config) {\n if (typeof config !== 'object' || config === null) {\n throw new Error('配置参数必须是一个非空对象');\n }\n globalConfig = { ...globalConfig, ...config };\n return { ...globalConfig };\n}\n\n/**\n * 获取当前全局配置\n * @returns {Object} 全局配置\n */\nfunction getGlobalConfig() {\n return { ...globalConfig };\n}\n\nexport { setGlobalConfig, getGlobalConfig };","// 加载器映射表(存储内置+自定义加载器)\nconst loaderMap = new Map();\n\n/**\n * 通用资源加载Promise封装\n * @param {string} url - 资源地址\n * @param {Function} loadHandler - 具体的资源加载处理函数\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 加载结果Promise\n */\nfunction wrapLoadPromise(url, loadHandler, timeout) {\n return new Promise((resolve, reject) => {\n // 超时处理\n const timeoutTimer = setTimeout(() => {\n reject(new Error(`Resource ${url} load timeout (${timeout}ms)`));\n }, timeout);\n\n // 执行具体加载逻辑\n loadHandler(url)\n .then((result) => {\n clearTimeout(timeoutTimer);\n resolve({\n url,\n success: true,\n data: result,\n error: null,\n });\n })\n .catch((error) => {\n clearTimeout(timeoutTimer);\n reject({\n url,\n success: false,\n data: null,\n error,\n });\n });\n });\n}\n\n// --------------- 内置JS加载器 ---------------\nfunction jsLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.src = url;\n script.async = false; // 保持加载顺序(不开启异步)\n\n script.onload = () => {\n resolve(script);\n document.head.removeChild(script); // 可选:加载完成后移除标签,避免污染DOM\n };\n\n script.onerror = () => {\n reject(new Error(`JS resource ${url} load failed`));\n document.head.removeChild(script);\n };\n\n document.head.appendChild(script);\n });\n}\n\n// --------------- 内置CSS加载器 ---------------\nfunction cssLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n\n link.onload = () => {\n resolve(link);\n };\n\n link.onerror = () => {\n reject(new Error(`CSS resource ${url} load failed`));\n };\n\n document.head.appendChild(link);\n });\n}\n\n// 初始化内置加载器\nloaderMap.set('js', jsLoaderHandler);\nloaderMap.set('css', cssLoaderHandler);\n\n/**\n * 注册自定义加载器的方法(导出)\n * @param {string} type - 资源类型(唯一标识)\n * @param {Function} handler - 加载处理函数,接收url参数,返回Promise\n */\nfunction registerLoader(type, handler) {\n if (typeof type !== 'string' || type.trim() === '') {\n throw new Error('资源类型必须是非空字符串');\n }\n if (typeof handler !== 'function' || handler.constructor.name !== 'Function') {\n throw new Error('加载器必须是一个函数,且返回Promise对象');\n }\n if (loaderMap.has(type)) {\n console.warn(`类型为${type}的加载器已存在,将被覆盖`);\n }\n loaderMap.set(type, handler);\n}\n\n/**\n * 获取对应类型的加载器\n * @param {string} type - 资源类型\n * @returns {Function} 加载器处理函数\n */\nfunction getLoader(type) {\n if (!loaderMap.has(type)) {\n throw new Error(`未找到${type}类型的加载器,请先注册自定义加载器`);\n }\n return loaderMap.get(type);\n}\n\nexport { registerLoader, getLoader, wrapLoadPromise }; // 导出wrapLoadPromise,避免冗余","import {getGlobalConfig} from './config.js';\nimport {getLoader, wrapLoadPromise} from './loader.js';\n\n/**\n * 检测循环依赖(深度优先遍历,配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n * @param {number} currentId - 当前资源ID\n * @param {Set} visited - 已访问的资源ID集合\n * @param {Set} visiting - 正在访问的资源ID集合(用于检测环)\n */\nfunction detectCycle(configList, currentId, visited, visiting) {\n const currentConfig = configList.find(item => item.name === currentId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${currentId}的资源配置`);\n }\n\n // 若正在访问中,说明存在循环依赖\n if (visiting.has(currentId)) {\n throw new Error(`检测到循环依赖:${Array.from(visiting).join(' -> ')} -> ${currentId}`);\n }\n\n // 若已访问过,直接返回(无需重复检测)\n if (visited.has(currentId)) {\n return;\n }\n\n // 标记为正在访问\n visiting.add(currentId);\n // 递归检测依赖项(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n detectCycle(configList, depId, visited, visiting);\n }\n // 标记为已访问,移出正在访问集合\n visiting.delete(currentId);\n visited.add(currentId);\n}\n\n/**\n * 预检测所有资源的循环依赖(配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n */\nfunction checkAllCycles(configList) {\n const visited = new Set();\n for (const config of configList) {\n detectCycle(configList, config.name, visited, new Set());\n }\n}\n\n/**\n * 递归加载单个资源及其所有依赖(保证依赖先加载,配置字段改为dependencies)\n * @param {string|number} resourceId - 资源ID\n * @param {Array} configList - 完整配置数组\n * @param {number} timeout - 超时时间\n * @param {Map} loadedMap - 已加载资源的结果缓存\n */\nasync function loadResourceWithDeps(resourceId, configList, timeout, loadedMap) {\n // 若已加载,直接返回缓存结果\n if (loadedMap.has(resourceId)) {\n return loadedMap.get(resourceId);\n }\n\n const currentConfig = configList.find(item => item.name === resourceId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${resourceId}的资源配置`);\n }\n\n // 1. 先加载所有依赖(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n await loadResourceWithDeps(depId, configList, timeout, loadedMap);\n }\n\n // 2. 再加载当前资源的urls(顺序加载,一个成功即可)\n const {urls, type} = currentConfig;\n let loadResult = null;\n let status = 'success';\n let error = null;\n\n try {\n loadResult = await loadUrlsInOrder(urls, type, timeout);\n } catch (err) {\n status = 'failed';\n error = err;\n }\n\n // 3. 缓存加载结果\n const result = {\n resourceId,\n config: currentConfig,\n loadResult,\n status,\n error,\n };\n loadedMap.set(resourceId, result);\n return result;\n}\n\n/**\n * 按顺序加载urls,只需要一个成功即可\n * @param {Array} urls - 资源地址数组\n * @param {string} type - 资源类型\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 第一个成功的加载结果\n */\nasync function loadUrlsInOrder(urls, type, timeout) {\n if (!Array.isArray(urls) || urls.length === 0) {\n throw new Error('urls必须是非空数组');\n }\n\n const loader = getLoader(type);\n let lastError;\n\n // 按顺序遍历urls,直到有一个加载成功\n for (const url of urls) {\n try {\n return await wrapLoadPromise(url, loader, timeout);\n } catch (error) {\n lastError = error;\n continue; // 加载失败,继续下一个url\n }\n }\n\n // 所有url都加载失败,抛出最后一个错误\n throw new Error(`所有${type}类型资源加载失败,最后一个错误:${lastError?.message || '未知错误'}`);\n}\n\n/**\n * 核心加载调度方法(最终结果保持配置定义顺序)\n * @param {Array<ResourceConfig>} configList - 输入配置数组\n * @returns {Promise<ResourceLoadResult[]>} 按配置定义顺序的加载结果数组\n */\nasync function preloadResources(configList) {\n if (!Array.isArray(configList) || configList.length === 0) {\n throw new Error('配置数组必须是非空数组');\n }\n\n // 将 string[] 形式处理成 { name, urls, type } 形式\n configList = configList.map(item => {\n if (typeof item === 'string') {\n const url = new URL(item, window.location.href);\n return {\n name: url.pathname,\n urls: [item],\n type: url.pathname.split('.').pop() || 'js',\n };\n } else if (Array.isArray(item)) {\n if (!item.length) {\n return;\n }\n const url = new URL(item[0], window.location.href);\n return {\n name: url.pathname,\n urls: item,\n type: url.pathname.split('.').pop() || 'js',\n };\n } else {\n return item;\n }\n }).filter(Boolean);\n\n // 1. 获取全局配置\n const {timeout: globalTimeout} = getGlobalConfig();\n\n // 2. 预检测所有循环依赖(防止无限递归)\n checkAllCycles(configList);\n\n // 3. 初始化缓存(存储已加载资源结果,避免重复加载)\n const loadedMap = new Map();\n\n // 4. 按配置定义的顺序,并行加载同层级无依赖资源(保证依赖先加载,结果保留原始顺序)\n const rawOrderPromises = configList.map(async (config) => {\n return await loadResourceWithDeps(config.name, configList, globalTimeout, loadedMap);\n });\n\n // 5. 等待所有资源加载完成,返回原始配置顺序的结果\n return Promise.all(rawOrderPromises).then(function (result) {\n if (result.find(item => item.error)) {\n return Promise.reject(result);\n }\n return result;\n });\n}\n\nexport {preloadResources};","import {preloadResources} from \"./scheduler.js\";\nimport {registerLoader} from \"./loader.js\";\nimport {setGlobalConfig} from \"./config.js\";\n\npreloadResources.registerLoader = registerLoader;\npreloadResources.setGlobalConfig = setGlobalConfig;\n\nexport default preloadResources;"],"names":["globalConfig","timeout","retry","loaderMap","Map","wrapLoadPromise","url","loadHandler","Promise","resolve","reject","timeoutTimer","setTimeout","Error","then","result","clearTimeout","success","data","error","catch","detectCycle","configList","currentId","visited","visiting","currentConfig","find","item","name","has","Array","from","join","add","dependencies","depId","delete","async","loadResourceWithDeps","resourceId","loadedMap","get","urls","type","loadResult","status","isArray","length","loader","getLoader","lastError","message","loadUrlsInOrder","err","config","set","preloadResources","map","URL","window","location","href","pathname","split","pop","filter","Boolean","globalTimeout","Set","checkAllCycles","rawOrderPromises","all","script","document","createElement","src","onload","head","removeChild","onerror","appendChild","link","rel","registerLoader","handler","trim","constructor","console","warn","setGlobalConfig"],"mappings":"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"}
@@ -272,7 +272,7 @@ async function loadUrlsInOrder(urls, type, timeout) {
272
272
  * @param {Array<ResourceConfig>} configList - 输入配置数组
273
273
  * @returns {Promise<ResourceLoadResult[]>} 按配置定义顺序的加载结果数组
274
274
  */
275
- async function resourcePreloader(configList) {
275
+ async function preloadResources(configList) {
276
276
  if (!Array.isArray(configList) || configList.length === 0) {
277
277
  throw new Error('配置数组必须是非空数组');
278
278
  }
@@ -324,5 +324,5 @@ async function resourcePreloader(configList) {
324
324
  });
325
325
  }
326
326
 
327
- export { resourcePreloader as default, registerLoader, resourcePreloader, setGlobalConfig };
327
+ export { preloadResources as default, preloadResources, registerLoader, setGlobalConfig };
328
328
  //# sourceMappingURL=resource-loader.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resource-loader.esm.js","sources":["../src/config.js","../src/loader.js","../src/scheduler.js"],"sourcesContent":["// 默认公共配置\nconst defaultConfig = {\n timeout: 1000, // 默认超时时间1s\n retry: 0, // 默认不重试\n};\n\nlet globalConfig = { ...defaultConfig };\n\n/**\n * 配置公共配置的方法(导出)\n * @param {Object} config - 需覆盖的公共配置\n * @returns {Object} 合并后的最终全局配置\n */\nfunction setGlobalConfig(config) {\n if (typeof config !== 'object' || config === null) {\n throw new Error('配置参数必须是一个非空对象');\n }\n globalConfig = { ...globalConfig, ...config };\n return { ...globalConfig };\n}\n\n/**\n * 获取当前全局配置\n * @returns {Object} 全局配置\n */\nfunction getGlobalConfig() {\n return { ...globalConfig };\n}\n\nexport { setGlobalConfig, getGlobalConfig };","// 加载器映射表(存储内置+自定义加载器)\nconst loaderMap = new Map();\n\n/**\n * 通用资源加载Promise封装\n * @param {string} url - 资源地址\n * @param {Function} loadHandler - 具体的资源加载处理函数\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 加载结果Promise\n */\nfunction wrapLoadPromise(url, loadHandler, timeout) {\n return new Promise((resolve, reject) => {\n // 超时处理\n const timeoutTimer = setTimeout(() => {\n reject(new Error(`Resource ${url} load timeout (${timeout}ms)`));\n }, timeout);\n\n // 执行具体加载逻辑\n loadHandler(url)\n .then((result) => {\n clearTimeout(timeoutTimer);\n resolve({\n url,\n success: true,\n data: result,\n error: null,\n });\n })\n .catch((error) => {\n clearTimeout(timeoutTimer);\n reject({\n url,\n success: false,\n data: null,\n error,\n });\n });\n });\n}\n\n// --------------- 内置JS加载器 ---------------\nfunction jsLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.src = url;\n script.async = false; // 保持加载顺序(不开启异步)\n\n script.onload = () => {\n resolve(script);\n document.head.removeChild(script); // 可选:加载完成后移除标签,避免污染DOM\n };\n\n script.onerror = () => {\n reject(new Error(`JS resource ${url} load failed`));\n document.head.removeChild(script);\n };\n\n document.head.appendChild(script);\n });\n}\n\n// --------------- 内置CSS加载器 ---------------\nfunction cssLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n\n link.onload = () => {\n resolve(link);\n };\n\n link.onerror = () => {\n reject(new Error(`CSS resource ${url} load failed`));\n };\n\n document.head.appendChild(link);\n });\n}\n\n// 初始化内置加载器\nloaderMap.set('js', jsLoaderHandler);\nloaderMap.set('css', cssLoaderHandler);\n\n/**\n * 注册自定义加载器的方法(导出)\n * @param {string} type - 资源类型(唯一标识)\n * @param {Function} handler - 加载处理函数,接收url参数,返回Promise\n */\nfunction registerLoader(type, handler) {\n if (typeof type !== 'string' || type.trim() === '') {\n throw new Error('资源类型必须是非空字符串');\n }\n if (typeof handler !== 'function' || handler.constructor.name !== 'Function') {\n throw new Error('加载器必须是一个函数,且返回Promise对象');\n }\n if (loaderMap.has(type)) {\n console.warn(`类型为${type}的加载器已存在,将被覆盖`);\n }\n loaderMap.set(type, handler);\n}\n\n/**\n * 获取对应类型的加载器\n * @param {string} type - 资源类型\n * @returns {Function} 加载器处理函数\n */\nfunction getLoader(type) {\n if (!loaderMap.has(type)) {\n throw new Error(`未找到${type}类型的加载器,请先注册自定义加载器`);\n }\n return loaderMap.get(type);\n}\n\nexport { registerLoader, getLoader, wrapLoadPromise }; // 导出wrapLoadPromise,避免冗余","import {getGlobalConfig} from './config.js';\nimport {getLoader, wrapLoadPromise} from './loader.js';\n\n/**\n * 检测循环依赖(深度优先遍历,配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n * @param {number} currentId - 当前资源ID\n * @param {Set} visited - 已访问的资源ID集合\n * @param {Set} visiting - 正在访问的资源ID集合(用于检测环)\n */\nfunction detectCycle(configList, currentId, visited, visiting) {\n const currentConfig = configList.find(item => item.name === currentId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${currentId}的资源配置`);\n }\n\n // 若正在访问中,说明存在循环依赖\n if (visiting.has(currentId)) {\n throw new Error(`检测到循环依赖:${Array.from(visiting).join(' -> ')} -> ${currentId}`);\n }\n\n // 若已访问过,直接返回(无需重复检测)\n if (visited.has(currentId)) {\n return;\n }\n\n // 标记为正在访问\n visiting.add(currentId);\n // 递归检测依赖项(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n detectCycle(configList, depId, visited, visiting);\n }\n // 标记为已访问,移出正在访问集合\n visiting.delete(currentId);\n visited.add(currentId);\n}\n\n/**\n * 预检测所有资源的循环依赖(配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n */\nfunction checkAllCycles(configList) {\n const visited = new Set();\n for (const config of configList) {\n detectCycle(configList, config.name, visited, new Set());\n }\n}\n\n/**\n * 递归加载单个资源及其所有依赖(保证依赖先加载,配置字段改为dependencies)\n * @param {string|number} resourceId - 资源ID\n * @param {Array} configList - 完整配置数组\n * @param {number} timeout - 超时时间\n * @param {Map} loadedMap - 已加载资源的结果缓存\n */\nasync function loadResourceWithDeps(resourceId, configList, timeout, loadedMap) {\n // 若已加载,直接返回缓存结果\n if (loadedMap.has(resourceId)) {\n return loadedMap.get(resourceId);\n }\n\n const currentConfig = configList.find(item => item.name === resourceId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${resourceId}的资源配置`);\n }\n\n // 1. 先加载所有依赖(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n await loadResourceWithDeps(depId, configList, timeout, loadedMap);\n }\n\n // 2. 再加载当前资源的urls(顺序加载,一个成功即可)\n const {urls, type} = currentConfig;\n let loadResult = null;\n let status = 'success';\n let error = null;\n\n try {\n loadResult = await loadUrlsInOrder(urls, type, timeout);\n } catch (err) {\n status = 'failed';\n error = err;\n }\n\n // 3. 缓存加载结果\n const result = {\n resourceId,\n config: currentConfig,\n loadResult,\n status,\n error,\n };\n loadedMap.set(resourceId, result);\n return result;\n}\n\n/**\n * 按顺序加载urls,只需要一个成功即可\n * @param {Array} urls - 资源地址数组\n * @param {string} type - 资源类型\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 第一个成功的加载结果\n */\nasync function loadUrlsInOrder(urls, type, timeout) {\n if (!Array.isArray(urls) || urls.length === 0) {\n throw new Error('urls必须是非空数组');\n }\n\n const loader = getLoader(type);\n let lastError;\n\n // 按顺序遍历urls,直到有一个加载成功\n for (const url of urls) {\n try {\n return await wrapLoadPromise(url, loader, timeout);\n } catch (error) {\n lastError = error;\n continue; // 加载失败,继续下一个url\n }\n }\n\n // 所有url都加载失败,抛出最后一个错误\n throw new Error(`所有${type}类型资源加载失败,最后一个错误:${lastError?.message || '未知错误'}`);\n}\n\n/**\n * 核心加载调度方法(最终结果保持配置定义顺序)\n * @param {Array<ResourceConfig>} configList - 输入配置数组\n * @returns {Promise<ResourceLoadResult[]>} 按配置定义顺序的加载结果数组\n */\nasync function resourcePreloader(configList) {\n if (!Array.isArray(configList) || configList.length === 0) {\n throw new Error('配置数组必须是非空数组');\n }\n\n // 将 string[] 形式处理成 { name, urls, type } 形式\n configList = configList.map(item => {\n if (typeof item === 'string') {\n const url = new URL(item, window.location.href);\n return {\n name: url.pathname,\n urls: [item],\n type: url.pathname.split('.').pop() || 'js',\n };\n } else if (Array.isArray(item)) {\n if (!item.length) {\n return;\n }\n const url = new URL(item[0], window.location.href);\n return {\n name: url.pathname,\n urls: item,\n type: url.pathname.split('.').pop() || 'js',\n };\n } else {\n return item;\n }\n }).filter(Boolean);\n\n // 1. 获取全局配置\n const {timeout: globalTimeout} = getGlobalConfig();\n\n // 2. 预检测所有循环依赖(防止无限递归)\n checkAllCycles(configList);\n\n // 3. 初始化缓存(存储已加载资源结果,避免重复加载)\n const loadedMap = new Map();\n\n // 4. 按配置定义的顺序,并行加载同层级无依赖资源(保证依赖先加载,结果保留原始顺序)\n const rawOrderPromises = configList.map(async (config) => {\n return await loadResourceWithDeps(config.name, configList, globalTimeout, loadedMap);\n });\n\n // 5. 等待所有资源加载完成,返回原始配置顺序的结果\n return Promise.all(rawOrderPromises).then(function (result) {\n if (result.find(item => item.error)) {\n return Promise.reject(result);\n }\n return result;\n });\n}\n\nexport {resourcePreloader};"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resource-loader.esm.js","sources":["../src/config.js","../src/loader.js","../src/scheduler.js"],"sourcesContent":["// 默认公共配置\nconst defaultConfig = {\n timeout: 1000, // 默认超时时间1s\n retry: 0, // 默认不重试\n};\n\nlet globalConfig = { ...defaultConfig };\n\n/**\n * 配置公共配置的方法(导出)\n * @param {Object} config - 需覆盖的公共配置\n * @returns {Object} 合并后的最终全局配置\n */\nfunction setGlobalConfig(config) {\n if (typeof config !== 'object' || config === null) {\n throw new Error('配置参数必须是一个非空对象');\n }\n globalConfig = { ...globalConfig, ...config };\n return { ...globalConfig };\n}\n\n/**\n * 获取当前全局配置\n * @returns {Object} 全局配置\n */\nfunction getGlobalConfig() {\n return { ...globalConfig };\n}\n\nexport { setGlobalConfig, getGlobalConfig };","// 加载器映射表(存储内置+自定义加载器)\nconst loaderMap = new Map();\n\n/**\n * 通用资源加载Promise封装\n * @param {string} url - 资源地址\n * @param {Function} loadHandler - 具体的资源加载处理函数\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 加载结果Promise\n */\nfunction wrapLoadPromise(url, loadHandler, timeout) {\n return new Promise((resolve, reject) => {\n // 超时处理\n const timeoutTimer = setTimeout(() => {\n reject(new Error(`Resource ${url} load timeout (${timeout}ms)`));\n }, timeout);\n\n // 执行具体加载逻辑\n loadHandler(url)\n .then((result) => {\n clearTimeout(timeoutTimer);\n resolve({\n url,\n success: true,\n data: result,\n error: null,\n });\n })\n .catch((error) => {\n clearTimeout(timeoutTimer);\n reject({\n url,\n success: false,\n data: null,\n error,\n });\n });\n });\n}\n\n// --------------- 内置JS加载器 ---------------\nfunction jsLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.src = url;\n script.async = false; // 保持加载顺序(不开启异步)\n\n script.onload = () => {\n resolve(script);\n document.head.removeChild(script); // 可选:加载完成后移除标签,避免污染DOM\n };\n\n script.onerror = () => {\n reject(new Error(`JS resource ${url} load failed`));\n document.head.removeChild(script);\n };\n\n document.head.appendChild(script);\n });\n}\n\n// --------------- 内置CSS加载器 ---------------\nfunction cssLoaderHandler(url) {\n return new Promise((resolve, reject) => {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = url;\n\n link.onload = () => {\n resolve(link);\n };\n\n link.onerror = () => {\n reject(new Error(`CSS resource ${url} load failed`));\n };\n\n document.head.appendChild(link);\n });\n}\n\n// 初始化内置加载器\nloaderMap.set('js', jsLoaderHandler);\nloaderMap.set('css', cssLoaderHandler);\n\n/**\n * 注册自定义加载器的方法(导出)\n * @param {string} type - 资源类型(唯一标识)\n * @param {Function} handler - 加载处理函数,接收url参数,返回Promise\n */\nfunction registerLoader(type, handler) {\n if (typeof type !== 'string' || type.trim() === '') {\n throw new Error('资源类型必须是非空字符串');\n }\n if (typeof handler !== 'function' || handler.constructor.name !== 'Function') {\n throw new Error('加载器必须是一个函数,且返回Promise对象');\n }\n if (loaderMap.has(type)) {\n console.warn(`类型为${type}的加载器已存在,将被覆盖`);\n }\n loaderMap.set(type, handler);\n}\n\n/**\n * 获取对应类型的加载器\n * @param {string} type - 资源类型\n * @returns {Function} 加载器处理函数\n */\nfunction getLoader(type) {\n if (!loaderMap.has(type)) {\n throw new Error(`未找到${type}类型的加载器,请先注册自定义加载器`);\n }\n return loaderMap.get(type);\n}\n\nexport { registerLoader, getLoader, wrapLoadPromise }; // 导出wrapLoadPromise,避免冗余","import {getGlobalConfig} from './config.js';\nimport {getLoader, wrapLoadPromise} from './loader.js';\n\n/**\n * 检测循环依赖(深度优先遍历,配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n * @param {number} currentId - 当前资源ID\n * @param {Set} visited - 已访问的资源ID集合\n * @param {Set} visiting - 正在访问的资源ID集合(用于检测环)\n */\nfunction detectCycle(configList, currentId, visited, visiting) {\n const currentConfig = configList.find(item => item.name === currentId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${currentId}的资源配置`);\n }\n\n // 若正在访问中,说明存在循环依赖\n if (visiting.has(currentId)) {\n throw new Error(`检测到循环依赖:${Array.from(visiting).join(' -> ')} -> ${currentId}`);\n }\n\n // 若已访问过,直接返回(无需重复检测)\n if (visited.has(currentId)) {\n return;\n }\n\n // 标记为正在访问\n visiting.add(currentId);\n // 递归检测依赖项(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n detectCycle(configList, depId, visited, visiting);\n }\n // 标记为已访问,移出正在访问集合\n visiting.delete(currentId);\n visited.add(currentId);\n}\n\n/**\n * 预检测所有资源的循环依赖(配置字段改为dependencies)\n * @param {Array} configList - 完整配置数组\n */\nfunction checkAllCycles(configList) {\n const visited = new Set();\n for (const config of configList) {\n detectCycle(configList, config.name, visited, new Set());\n }\n}\n\n/**\n * 递归加载单个资源及其所有依赖(保证依赖先加载,配置字段改为dependencies)\n * @param {string|number} resourceId - 资源ID\n * @param {Array} configList - 完整配置数组\n * @param {number} timeout - 超时时间\n * @param {Map} loadedMap - 已加载资源的结果缓存\n */\nasync function loadResourceWithDeps(resourceId, configList, timeout, loadedMap) {\n // 若已加载,直接返回缓存结果\n if (loadedMap.has(resourceId)) {\n return loadedMap.get(resourceId);\n }\n\n const currentConfig = configList.find(item => item.name === resourceId);\n if (!currentConfig) {\n throw new Error(`未找到ID为${resourceId}的资源配置`);\n }\n\n // 1. 先加载所有依赖(改为dependencies)\n const dependencies = currentConfig.dependencies || [];\n for (const depId of dependencies) {\n await loadResourceWithDeps(depId, configList, timeout, loadedMap);\n }\n\n // 2. 再加载当前资源的urls(顺序加载,一个成功即可)\n const {urls, type} = currentConfig;\n let loadResult = null;\n let status = 'success';\n let error = null;\n\n try {\n loadResult = await loadUrlsInOrder(urls, type, timeout);\n } catch (err) {\n status = 'failed';\n error = err;\n }\n\n // 3. 缓存加载结果\n const result = {\n resourceId,\n config: currentConfig,\n loadResult,\n status,\n error,\n };\n loadedMap.set(resourceId, result);\n return result;\n}\n\n/**\n * 按顺序加载urls,只需要一个成功即可\n * @param {Array} urls - 资源地址数组\n * @param {string} type - 资源类型\n * @param {number} timeout - 超时时间\n * @returns {Promise<Object>} 第一个成功的加载结果\n */\nasync function loadUrlsInOrder(urls, type, timeout) {\n if (!Array.isArray(urls) || urls.length === 0) {\n throw new Error('urls必须是非空数组');\n }\n\n const loader = getLoader(type);\n let lastError;\n\n // 按顺序遍历urls,直到有一个加载成功\n for (const url of urls) {\n try {\n return await wrapLoadPromise(url, loader, timeout);\n } catch (error) {\n lastError = error;\n continue; // 加载失败,继续下一个url\n }\n }\n\n // 所有url都加载失败,抛出最后一个错误\n throw new Error(`所有${type}类型资源加载失败,最后一个错误:${lastError?.message || '未知错误'}`);\n}\n\n/**\n * 核心加载调度方法(最终结果保持配置定义顺序)\n * @param {Array<ResourceConfig>} configList - 输入配置数组\n * @returns {Promise<ResourceLoadResult[]>} 按配置定义顺序的加载结果数组\n */\nasync function preloadResources(configList) {\n if (!Array.isArray(configList) || configList.length === 0) {\n throw new Error('配置数组必须是非空数组');\n }\n\n // 将 string[] 形式处理成 { name, urls, type } 形式\n configList = configList.map(item => {\n if (typeof item === 'string') {\n const url = new URL(item, window.location.href);\n return {\n name: url.pathname,\n urls: [item],\n type: url.pathname.split('.').pop() || 'js',\n };\n } else if (Array.isArray(item)) {\n if (!item.length) {\n return;\n }\n const url = new URL(item[0], window.location.href);\n return {\n name: url.pathname,\n urls: item,\n type: url.pathname.split('.').pop() || 'js',\n };\n } else {\n return item;\n }\n }).filter(Boolean);\n\n // 1. 获取全局配置\n const {timeout: globalTimeout} = getGlobalConfig();\n\n // 2. 预检测所有循环依赖(防止无限递归)\n checkAllCycles(configList);\n\n // 3. 初始化缓存(存储已加载资源结果,避免重复加载)\n const loadedMap = new Map();\n\n // 4. 按配置定义的顺序,并行加载同层级无依赖资源(保证依赖先加载,结果保留原始顺序)\n const rawOrderPromises = configList.map(async (config) => {\n return await loadResourceWithDeps(config.name, configList, globalTimeout, loadedMap);\n });\n\n // 5. 等待所有资源加载完成,返回原始配置顺序的结果\n return Promise.all(rawOrderPromises).then(function (result) {\n if (result.find(item => item.error)) {\n return Promise.reject(result);\n }\n return result;\n });\n}\n\nexport {preloadResources};"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- let e={timeout:1e3,retry:0};function r(r){if("object"!=typeof r||null===r)throw new Error("配置参数必须是一个非空对象");return e={...e,...r},{...e}}const n=new Map;function t(e,r,n){return new Promise((t,o)=>{const s=setTimeout(()=>{o(new Error(`Resource ${e} load timeout (${n}ms)`))},n);r(e).then(r=>{clearTimeout(s),t({url:e,success:!0,data:r,error:null})}).catch(r=>{clearTimeout(s),o({url:e,success:!1,data:null,error:r})})})}function o(e,r){if("string"!=typeof e||""===e.trim())throw new Error("资源类型必须是非空字符串");if("function"!=typeof r||"Function"!==r.constructor.name)throw new Error("加载器必须是一个函数,且返回Promise对象");n.has(e)&&console.warn(`类型为${e}的加载器已存在,将被覆盖`),n.set(e,r)}function s(e,r,n,t){const o=e.find(e=>e.name===r);if(!o)throw new Error(`未找到ID为${r}的资源配置`);if(t.has(r))throw new Error(`检测到循环依赖:${Array.from(t).join(" -> ")} -> ${r}`);if(n.has(r))return;t.add(r);const a=o.dependencies||[];for(const r of a)s(e,r,n,t);t.delete(r),n.add(r)}async function a(e,r,o,s){if(s.has(e))return s.get(e);const c=r.find(r=>r.name===e);if(!c)throw new Error(`未找到ID为${e}的资源配置`);const i=c.dependencies||[];for(const e of i)await a(e,r,o,s);const{urls:u,type:l}=c;let f=null,d="success",w=null;try{f=await async function(e,r,o){if(!Array.isArray(e)||0===e.length)throw new Error("urls必须是非空数组");const s=function(e){if(!n.has(e))throw new Error(`未找到${e}类型的加载器,请先注册自定义加载器`);return n.get(e)}(r);let a;for(const r of e)try{return await t(r,s,o)}catch(e){a=e;continue}throw new Error(`所有${r}类型资源加载失败,最后一个错误:${a?.message||"未知错误"}`)}(u,l,o)}catch(e){d="failed",w=e}const h={resourceId:e,config:c,loadResult:f,status:d,error:w};return s.set(e,h),h}async function c(r){if(!Array.isArray(r)||0===r.length)throw new Error("配置数组必须是非空数组");r=r.map(e=>{if("string"==typeof e){const r=new URL(e,window.location.href);return{name:r.pathname,urls:[e],type:r.pathname.split(".").pop()||"js"}}if(Array.isArray(e)){if(!e.length)return;const r=new URL(e[0],window.location.href);return{name:r.pathname,urls:e,type:r.pathname.split(".").pop()||"js"}}return e}).filter(Boolean);const{timeout:n}={...e};!function(e){const r=new Set;for(const n of e)s(e,n.name,r,new Set)}(r);const t=new Map,o=r.map(async e=>await a(e.name,r,n,t));return Promise.all(o).then(function(e){return e.find(e=>e.error)?Promise.reject(e):e})}n.set("js",function(e){return new Promise((r,n)=>{const t=document.createElement("script");t.type="text/javascript",t.src=e,t.async=!1,t.onload=()=>{r(t),document.head.removeChild(t)},t.onerror=()=>{n(new Error(`JS resource ${e} load failed`)),document.head.removeChild(t)},document.head.appendChild(t)})}),n.set("css",function(e){return new Promise((r,n)=>{const t=document.createElement("link");t.rel="stylesheet",t.href=e,t.onload=()=>{r(t)},t.onerror=()=>{n(new Error(`CSS resource ${e} load failed`))},document.head.appendChild(t)})});export{c as default,o as registerLoader,c as resourcePreloader,r as setGlobalConfig};
1
+ let e={timeout:1e3,retry:0};function r(r){if("object"!=typeof r||null===r)throw new Error("配置参数必须是一个非空对象");return e={...e,...r},{...e}}const n=new Map;function t(e,r,n){return new Promise((t,o)=>{const s=setTimeout(()=>{o(new Error(`Resource ${e} load timeout (${n}ms)`))},n);r(e).then(r=>{clearTimeout(s),t({url:e,success:!0,data:r,error:null})}).catch(r=>{clearTimeout(s),o({url:e,success:!1,data:null,error:r})})})}function o(e,r){if("string"!=typeof e||""===e.trim())throw new Error("资源类型必须是非空字符串");if("function"!=typeof r||"Function"!==r.constructor.name)throw new Error("加载器必须是一个函数,且返回Promise对象");n.has(e)&&console.warn(`类型为${e}的加载器已存在,将被覆盖`),n.set(e,r)}function s(e,r,n,t){const o=e.find(e=>e.name===r);if(!o)throw new Error(`未找到ID为${r}的资源配置`);if(t.has(r))throw new Error(`检测到循环依赖:${Array.from(t).join(" -> ")} -> ${r}`);if(n.has(r))return;t.add(r);const a=o.dependencies||[];for(const r of a)s(e,r,n,t);t.delete(r),n.add(r)}async function a(e,r,o,s){if(s.has(e))return s.get(e);const c=r.find(r=>r.name===e);if(!c)throw new Error(`未找到ID为${e}的资源配置`);const i=c.dependencies||[];for(const e of i)await a(e,r,o,s);const{urls:u,type:l}=c;let f=null,d="success",w=null;try{f=await async function(e,r,o){if(!Array.isArray(e)||0===e.length)throw new Error("urls必须是非空数组");const s=function(e){if(!n.has(e))throw new Error(`未找到${e}类型的加载器,请先注册自定义加载器`);return n.get(e)}(r);let a;for(const r of e)try{return await t(r,s,o)}catch(e){a=e;continue}throw new Error(`所有${r}类型资源加载失败,最后一个错误:${a?.message||"未知错误"}`)}(u,l,o)}catch(e){d="failed",w=e}const h={resourceId:e,config:c,loadResult:f,status:d,error:w};return s.set(e,h),h}async function c(r){if(!Array.isArray(r)||0===r.length)throw new Error("配置数组必须是非空数组");r=r.map(e=>{if("string"==typeof e){const r=new URL(e,window.location.href);return{name:r.pathname,urls:[e],type:r.pathname.split(".").pop()||"js"}}if(Array.isArray(e)){if(!e.length)return;const r=new URL(e[0],window.location.href);return{name:r.pathname,urls:e,type:r.pathname.split(".").pop()||"js"}}return e}).filter(Boolean);const{timeout:n}={...e};!function(e){const r=new Set;for(const n of e)s(e,n.name,r,new Set)}(r);const t=new Map,o=r.map(async e=>await a(e.name,r,n,t));return Promise.all(o).then(function(e){return e.find(e=>e.error)?Promise.reject(e):e})}n.set("js",function(e){return new Promise((r,n)=>{const t=document.createElement("script");t.type="text/javascript",t.src=e,t.async=!1,t.onload=()=>{r(t),document.head.removeChild(t)},t.onerror=()=>{n(new Error(`JS resource ${e} load failed`)),document.head.removeChild(t)},document.head.appendChild(t)})}),n.set("css",function(e){return new Promise((r,n)=>{const t=document.createElement("link");t.rel="stylesheet",t.href=e,t.onload=()=>{r(t)},t.onerror=()=>{n(new Error(`CSS resource ${e} load failed`))},document.head.appendChild(t)})});export{c as default,c as preloadResources,o as registerLoader,r as setGlobalConfig};
2
2
  //# sourceMappingURL=resource-loader.esm.min.js.map