{"id":19545181,"url":"https://github.com/scscms/loadjavascript","last_synced_at":"2026-06-19T14:31:14.767Z","repository":{"id":93554987,"uuid":"44107729","full_name":"scscms/LoadJavaScript","owner":"scscms","description":"After loading the javascript callback function","archived":false,"fork":false,"pushed_at":"2016-06-13T09:41:02.000Z","size":7,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-26T05:42:52.192Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scscms.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-10-12T13:02:05.000Z","updated_at":"2016-06-13T09:59:18.000Z","dependencies_parsed_at":"2023-10-02T08:04:14.938Z","dependency_job_id":null,"html_url":"https://github.com/scscms/LoadJavaScript","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/scscms/LoadJavaScript","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scscms%2FLoadJavaScript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scscms%2FLoadJavaScript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scscms%2FLoadJavaScript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scscms%2FLoadJavaScript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scscms","download_url":"https://codeload.github.com/scscms/LoadJavaScript/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scscms%2FLoadJavaScript/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34536274,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-19T02:00:06.005Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T03:36:14.765Z","updated_at":"2026-06-19T14:31:14.751Z","avatar_url":"https://github.com/scscms.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LoadJavaScript\u003csup\u003eshine\u003c/sup\u003e\n### 前言\nJavaScript文件在前端优化上来说，都是建议多个文件合并压缩加载。但当文件过于庞大时，而且有些文件本身就是次要，或者需要延时执行的我们还是建议分开加载与执行。\n\n### 简单粗暴加载\n```JavaScript\ndocument.writeln('\u003cscript src=\"js.js\"\u003e\u003c\\/script\u003e');\ndocument.write('\u003cscript src=\"js.js\"\u003e\u003c\\/script\u003e');\n```\n直接写入js标签，js挟持就常常使用这种简单粗暴方法。此方法还会造成文档阻塞。\n\n### 优雅加载\n```JavaScript\nfunction insertJs(url){\n    var _doc = document,\n        script = _doc.createElement(\"script\"),\n        head = _doc.getElementsByTagName(\"head\")[0],\n        baseElement = head.getElementsByTagName(\"base\");\n    script.type = \"text/javascript\";\n    script.src = url;\n    //IE6下script必须插入到base前，以防引起bug\n    baseElement ? head.insertBefore(script, baseElement[0]) : head.appendChild(script);\n}\n```\n此方法是创建script标签再插入head标签里。它并不会阻塞文档渲染。所以适合加载次要js文件。\n不过我们需要再改进一下函数，需要知道什么时候已经载完此js文件，好让我们调用回调函数。\n而script标签在IE8及以下是不支持onload事件，我们只能使用readystatechange事件。\nscript元素有一个readyState属性，它的值随着下载外部文件的过程而改变：\n\n* “uninitialized”默认状态\n* “loading”下载开始\n* “loaded”下载完成\n* “interactive”下载完成但尚不可用\n* “complete”所有数据已经准备好\n\n而且这些值并不一定全部出现，特别是我们需要的“loaded”和“complete”说不准谁会出现。\n```JavaScript\nfunction loadScript(url, callback) {\n    var script = document.createElement(\"script\"),\n        head = document.getElementsByTagName(\"head\")[0],\n        baseElement = document.getElementsByTagName(\"base\");\n    script.type = \"text/javascript\";\n    callback = Object.prototype.toString.call(callback) == '[object Function]' ? callback : function(){};\n    if (script.readyState) { //IE\n        script.onreadystatechange = function () {\n            if (script.readyState == \"loaded\" || script.readyState == \"complete\") {\n                script.onreadystatechange = null;\n                callback();\n            }\n        }\n    } else { //Others\n        script.onload = function () {\n            callback();\n        }\n    }\n    script.src = url;\n    baseElement ? head.insertBefore(script, baseElement[0]) : head.appendChild(script);\n}\n```\n而且我觉得这函数仍可精简下：\n```JavaScript\nfunction loadScript(url, callback) {\n    var script = document.createElement(\"script\"),\n        head = document.getElementsByTagName(\"head\")[0],\n        baseElement = document.getElementsByTagName(\"base\");\n    script.type = \"text/javascript\";\n    if(Object.prototype.toString.call(callback) == '[object Function]'){\n        script.onload = script.onreadystatechange = function() {\n            if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {\n                this.onload = this.onreadystatechange = null;\n                callback.call(this);\n            }\n        }\n    }\n    script.src = url;\n    baseElement ? head.insertBefore(script, baseElement[0]) : head.appendChild(script);\n}\n```\n此时应该没什么大问题了，突然一天想到假如要求几个js加载完才回调函数呢？这...\n```JavaScript\nfunction loadScripts(urls, callback) {\n    urls.splice !== Array.prototype.splice \u0026\u0026 (urls = [urls]);//确保是数组\n    (function(){\n        if (0 == urls.length) {\n            '[object Function]' == Object.prototype.toString.call(callback) \u0026\u0026 callback();\n        } else {\n            var callee = arguments.callee,//如果是严格模式就不要使用匿名函数模式\n                script = document.createElement(\"script\"),\n                head = document.getElementsByTagName(\"head\")[0],\n                baseElement = document.getElementsByTagName(\"base\");\n            script.type = \"text/javascript\";\n            script.onload = script.onreadystatechange = function() {\n                if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {\n                    this.onload = this.onreadystatechange = null;\n                    callee();\n                }\n            };\n            script.src = urls.shift();\n            baseElement ? head.insertBefore(script, baseElement[0]) : head.appendChild(script);\n        }\n    })();\n}\n```\n此方法仍需要考虑两个问题：\n\n* 1.是js超时加载，如果你项目有要求那么你需要添加超时机制。\n* 2.是js失败捕捉，上面脚本一旦遇到某个js加载失败，后继的js将不再加载，也不会触发回调。\n\n### JavaScript加载失败问题\n在非IE下，我们是可以使用onerror捕捉js加载失败问题。IE8及以下是没法捕捉失败问题，就算404、500错误readyState值也是正常出现：\n```JavaScript\nvar script = document.createElement(\"script\");\nscript.type = \"text/javascript\";\nscript.onreadystatechange = function() {\n    alert(this.readyState);\n    //IE7\\8正常弹出　loading loaded\n};\nscript.src = \"http://www.baidu.com/xxoo.js\";\ndocument.getElementsByTagName(\"head\")[0].appendChild(script);\n```\n满脸的黑线呀！那么应该怎么样获取IE失败问题呢？\n我的方法是替换判断，把js文件当vbscript来加载，因为vbscript文件载完会自动执行，如果能捕捉到window.onerror说明文件能正常加载成功。然后再以正常js来载入。\n当然如果文档本身是vbscript文件或是一个空文档就会误判：\n```JavaScript\nfunction loadScript(jsUrl, callBack) {\n        var _doc = document,\n                script = _doc.createElement(\"script\"),\n                head = _doc.head || _doc.getElementsByTagName(\"head\")[0] || _doc.documentElement;\n        '[object Function]' != Object.prototype.toString.call(callBack) \u0026\u0026 (callBack = function(){});\n        if (\"onload\" in script) {\n            //非IE和IE9及以上支持onload、onerror事件\n            script.type = \"text/javascript\";\n            script.onload = function () {\n                callBack.call(this,\"ok\");\n            };\n            script.onerror = function () {\n                callBack.call(this,\"no\");\n            };\n        } else {\n            var baseElement = head.getElementsByTagName(\"base\")[0],_err = 0;\n            script.language = \"vbscript\";\n            //假如您的脚本也使用了window.onerror请使用监听方法替换以免冲突\n            window.onerror = function(){\n                _err = 1;\n                return true;\n            };\n            script.attachEvent(\"onreadystatechange\",function(){\n                //vbscript成功载入将会先触发window.onerror\n                if (/loaded|complete/i.test(script.readyState)) {\n                    window.onerror = null;//清理监听事件\n                    if(_err){\n                        script.parentNode.removeChild(script);//移除vbscript节点\n                        script = document.createElement(\"script\");//再生成script节点并插入文档\n                        script.attachEvent(\"onreadystatechange\",function(){\n                            if (/loaded|complete/i.test(script.readyState)) {\n                                callBack.call(script, \"ok\");\n                            }\n                        });\n                        script.type = \"text/javascript\";\n                        script.src = jsUrl;\n                        baseElement ? head.insertBefore(script, baseElement) : head.appendChild(script);\n                    }else{\n                        callBack.call(script,\"no\");\n                    }\n                }\n            });\n        }\n        script.src = jsUrl;//必须先赋值后生成，否则影响readyState值\n        head.appendChild(script);\n    }\n    loadScript(\"http://www.baidu.com/xxoo.js?a=\" + Math.random(),\n        function (state) {\n            alert(\"ok\" == state ? \"成功\":\"失败\");\n        }\n    );\n```\n此方法唯一处理不够完美的是window.onerror事件，要留意事件冲突。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscscms%2Floadjavascript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscscms%2Floadjavascript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscscms%2Floadjavascript/lists"}