动态加载JavaScript的同步

我使用的模块模式,我想要做的事情之一是动态包括外部JavaScript文件,执行该文件,然后使用该文件中的函数/变量return { }我模块。

我无法弄清楚如何轻松地做到这一点。 是否有执行一个伪同步外部脚本加载任何标准的方法?

function myModule() { var tag = document.createElement("script"); tag.type = "text/javascript"; tag.src = "http://some/script.js"; document.getElementsByTagName('head')[0].appendChild(tag); //something should go here to ensure file is loaded before return is executed return { external: externalVariable } }

--------------解决方案-------------

只有一个办法,同步加载和执行脚本的资源,那就是使用同步XHR

这是如何做到这一点的一个例子

// get some kind of XMLHttpRequest
var xhrObj = createXMLHTTPObject();
// open and send a synchronous request
xhrObj.open('GET', "script.js", false);
xhrObj.send('');
// add the returned content to a newly created script tag
var se = document.createElement('script');
se.type = "text/javascript";
se.text = xhrObj.responseText;
document.getElementsByTagName('head')[0].appendChild(se);

但你不应该在一般使用同步请求,因为这将阻止一切。 但是他这样说,当然有场景,这是合适的。

我可能会重构包含函数到,虽然使用的onload处理程序的异步模式。

这是我用在我的应用程序的多个文件加载的代码。

Utilities.require = function (file, callback) {
callback = callback ||
function () {};
var filenode;
var jsfile_extension = /(.js)$/i;
var cssfile_extension = /(.css)$/i;

if (jsfile_extension.test(file)) {
filenode = document.createElement('script');
filenode.src = file;
// IE
filenode.onreadystatechange = function () {
if (filenode.readyState === 'loaded' || filenode.readyState === 'complete') {
filenode.onreadystatechange = null;
callback();
}
};
// others
filenode.onload = function () {
callback();
};
document.head.appendChild(filenode);
} else if (cssfile_extension.test(file)) {
filenode = document.createElement('link');
filenode.rel = 'stylesheet';
filenode.type = 'text/css';
filenode.href = file;
document.head.appendChild(filenode);
callback();
} else {
console.log("Unknown file type to load.")
}
};

Utilities.requireFiles = function () {
var index = 0;
return function (files, callback) {
index += 1;
Utilities.require(files[index - 1], callBackCounter);

function callBackCounter() {
if (index === files.length) {
index = 0;
callback();
} else {
Utilities.requireFiles(files, callback);
}
};
};
}();

和这个工具可用于通过

Utilities.requireFiles(["url1", "url2",....], function(){
//Call the init function in the loaded file.
})

接受的答案是不正确的。

加载文件同步是不一样的同步执行文件 - 这是在OP请求。

该接受的答案加载的文件同步,但确实没有什么比添加脚本标记到DOM。 仅仅因为使用appendChild()返回不反正保证脚本执行完毕,它的成员初始化使用。

唯一的(见警告)的方式,实现了有机磷农药的问题是同步加载脚本在XHR的陈述,然后阅读文本,并传递到任何的eval()或新功能()调用,并等待该函数返回。 这是为了保证加载并同步执行脚本的唯一途径。

我不作任何评论,这是否是一个明智的做法无论是从UI或安全的角度,但也有一定使用证明一个同步加载和执行情况。

警告:除非您使用的是网络工作者在这种情况下,只需要调用loadScripts();

查看此页出高性能的Javascript

基本上你告诉它的脚本加载,然后你可以给它一个回调函数来运行一次,它的完成。 我用这个生产,它的真棒。

你不能,不应该同步出于显而易见的原因进行服务器操作。 你可以做什么,不过,是有一个事件处理程序告诉你,当脚本加载:

tag.onreadystatechange = function() { if (this.readyState == 'complete' || this.readyState == 'loaded') this.onload({ target: this }); };

tag.onload = function(load) {/*init code here*/}

onreadystatechange代表团,从内存,一个解决方法IE浏览器,它具有片状的支持onload

如果你需要加载脚本的任意号码,只有当最后一个完成的进行,你不能使用XHR(例如,由于CORS限制),你可以做到以下几点。 这是不同步的,但确实允许一个回调来发生的确切时间的最后一个文件加载完成:

// Load <script> elements for all uris
// Invoke the whenDone callback function after the last URI has loaded
function loadScripts(uris,whenDone){
if (!uris.length) whenDone && whenDone();
else{
for (var wait=[],i=uris.length;i--;){
var tag = document.createElement('script');
tag.type = 'text/javascript';
tag.src = uris[i];
if (whenDone){
wait.push(tag)
tag.onload = maybeDone;
tag.onreadystatechange = maybeDone; // For IE8-
}
document.body.appendChild(tag);
}
}
function maybeDone(){
if (this.readyState===undefined || this.readyState==='complete'){
// Pull the tags out based on the actual element in case IE ever
// intermingles the onload and onreadystatechange handlers for the same
// script block before notifying for another one.
for (var i=wait.length;i--;) if (wait[i]==this) wait.splice(i,1);
if (!wait.length) whenDone();
}
}
}

编辑 :更新了IE7,IE8,IE9和工作(在怪癖模式)。 这些版本的IE不火的onload事件,但做onreadystatechange IE9在标准模式下触发兼而有之 onreadystatechange烧制前的所有脚本onload任何)。

基于此页面上有可能是一个小的机会,旧版本的IE浏览器将不会发送一个onreadystatechange事件readyState=='complete' 如果是这样的话(我无法重现此问题),那么上面的脚本将失败,您的回调将永远不会被调用。

var xhrObj = new XMLHttpRequest();
xhrObj.open('GET', '/filename.js', false);
xhrObj.send(null);
eval(xhrObj.responseText);

如果这是一个跨域请求,它将无法正常工作。 在这种情况下,你必须所需的文件上传到服务器,或做镜像PHP,输出它,并要求PHP。

使用jQuery(适用于跨域请求太):

$.getScript('/filename.js',callbackFunction);

callbackFunction将被同步调用。

对于加载多个脚本看到这个线程。

同肖恩的答案,但中,而不是创建一个脚本标记,只是对其进行评估。 这确保了代码实际上已经可以使用。

我曾与现有的回答这个问题(和其他的StackOverflow线程这个问题的变化)下面的问题(S):

  • 没有加载代码是可调试
  • 许多解决方案所需的回调知道什么时候加载结束,而不是真正的阻止,这意味着我会得到执行错误的立即调用加载(即加载)的代码。

或者,稍微更准确:

  • 没有加载代码为可调试(除了从HTML脚本标记块,当且仅当该溶液加入一个脚本元素到DOM和永远作为单独的可视脚本。)=>给出我多少脚本必须装载(和调试),这是不能接受的。
  • 使用'onreadystatechange的“或”的onload“事件的解决方案未能阻止,这是一个很大的问题,因为代码原来加载同步地使用'需要([文件名,'道场/ domready中']动态脚本);' 我被剥离出来道场。

我最终的解决方案,它加载脚本返回前,并拥有所有的脚本在调试器中正常访问(适用于Chrome至少)如下:

警告:下面的代码可能应该只在“发展” 模式(“ 释放”模式,我建议预包装和微小无动态脚本加载,或至少没有EVAL)。

//Code User TODO: you must create and set your own 'noEval' variable

require = function require(inFileName)
{
var aRequest
,aScript
,aScriptSource
;

//setup the full relative filename
inFileName =
window.location.protocol + '//'
+ window.location.host + '/'
+ inFileName;

//synchronously get the code
aRequest = new XMLHttpRequest();
aRequest.open('GET', inFileName, false);
aRequest.send();

//set the returned script text while adding special comment to auto include in debugger source listing:
aScriptSource = aRequest.responseText + '\n////# sourceURL=' + inFileName + '\n';

if(noEval)//<== **TODO: Provide + set condition variable yourself!!!!**
{
//create a dom element to hold the code
aScript = document.createElement('script');
aScript.type = 'text/javascript';

//set the script tag text, including the debugger id at the end!!
aScript.text = aScriptSource;

//append the code to the dom
document.getElementsByTagName('body')[0].appendChild(aScript);
}
else
{
eval(aScriptSource);
}
};

我用应用于div元素jQuery的load方法 。 就像是

<div id="js">
<!-- script will be inserted here -->
</div>

...

$("#js").load("path", function() { alert("callback!" });

您可以加载脚本几次,每次一脚本将完全取代一个较早的加载

分类:JavaScript的 时间:2015-03-15 人气:0
本文关键词: JavaScript的
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 0.228 (s). 10 q(s)