异步JavaScript动态包含
Asynchronously JavaScript dynamic includes
我有很多JavaScript文件,以三个为例:App.js、ChildApp.js(不止一个)和AjaxManager.js,而我添加的是AjaxManger.js。
ChildApp扩展了App,并且App依赖于AjaxManager。
应用程序中的构造函数:
function App() {
this.ajaxManager=new AjaxManager();//Need AjaxManager.js to import, especially when new ChildApp is called.
....
}
ChildApp的构造函数:
function ChildApp's() {
App.call(this); //
}
ChildApp.prototype = new App();
...
在遗留代码中,有几十个地方包含App.js,我不想复制和粘贴之前包含AjaxManager.js的代码。
但如果我没有很好地包括AjaxManager,我将在时出错
var app=new ChildApp();//ReferenceError: AjaxManager is not defined
因此,我在App.js的开始中使用以下代码:
if(typeof AjaxManager =='undefined'){
console.log('AjaxManager is not loaded , getting the script');
$.ajax({
url: .....//Url to load
dataType: "script",
async:false// How can I use async =true
});
}
但是我必须对请求使用async:false,这在控制台中向我显示了一个警告:主线程上的同步XMLHttpRequest已被弃用,因为它对最终用户的体验有不利影响
否则我会有错误:
ReferenceError: AjaxManager is not defined
我如何使用异步请求来加载脚本,并确保一切正常,但不会破坏我现有的功能。
更新:
在我问这个问题之前,我在App.js的开头或函数App()的开头尝试了
$.getScript(url)
,但同样的错误,我想应该在回调中放置一些与构造函数App
相关的东西,但我不知道如何放置。我希望我只能修改app.js或ajaxmanager.js,因为调用new app()或new ChildApp()的地方太多了
不要使用async: false
。这是一种非常糟糕的做法,因为它会阻塞UI线程,直到请求完成。
相反,您可以使用$.getScript
来缩短代码,并使用回调处理程序来执行依赖于正在加载的脚本的任何代码。试试这个:
if (typeof AjaxManager =='undefined') {
$.getScript('ajaxManager.js', processPage);
}
else {
// AjaxManager already loaded
processPage();
}
function processPage() {
// put your logic that relies on AjaxManager here
}
如果您想用jQuery按特定顺序加载三个脚本,可以使用$.getScript()
并将每个脚本链接到前一个脚本的已完成promise中。
$.getScript('AjaxManager.js').then(function() {
return $.getScript('App.js');
}).then(function() {
return $.getScript('ChildApp.js');
});
或者,如果你想把它变成一个函数,你可以把一系列脚本传递给:
function loadScripts(array) {
return array.reduce(function(p, scriptFile) {
return p.then(function() {
return $.getScript(scriptFile);
});
}, $.Deferred().resolve().promise());
}
loadScripts('AjaxManager.js', 'App.js', 'ChildApp.js');
// The order of the scripts in the array is the order they will be loaded.
如果您想测试它们以前是否已加载,那么您也可以为每个脚本传递一个测试符号,并将其合并到加载逻辑中。
function loadScripts(array) {
return array.reduce(function(p, obj) {
return p.then(function() {
if (typeof window[obj.testSymbol] === "undefined") {
return $.getScript(scriptFile);
} else {
return $.Deferred().resolve().promise();
}
});
}, $.Deferred().resolve().promise());
}
loadScripts(
{file: 'AjaxManager.js', testSymbol: 'AjaxManager'},
{file: 'App.js', testSymbol: 'App'},
{file: 'ChildApp.js', testSymbol: 'ChildApp'}
);
这将允许您根据需要多次尝试加载任何给定的脚本,而它实际上只加载一次。
仅供参考,$.getScript()
是一个异步操作。它调用在加载完成时传递给它的回调,或者解析它返回的promise。如果您希望某些操作只在$.getScript()
完成加载后进行,那么您必须将该代码放入回调中。
因此,如果您想在App()
构造函数中加载AjaxManager脚本,那么在构造函数返回之前,您不能这样做。在Javascript中,不建议您在构造函数中启动异步操作,因为没有好的方法来处理错误,并且在异步操作完成之前,您可能会有一个部分初始化的对象。
有关构造函数中异步操作的一些注释,请参阅本答案的后半部分。
- 如何在Jquery中的.ech()中包含动态添加的输入值
- 如何使用node.js抓取包含动态内容的页面
- 如何在PHP中包含动态Javascript页面的静态HTML结果
- 我将如何获取包含动态内容的页面的html
- 创建一个 html 表,其中包含动态扩展的列数以适应屏幕大小
- Angularjs:隐藏包含动态参数的网址的导航栏
- 包含动态内容的较长页面上的返回顶部链接
- 包含动态数字的变量
- XMLHttpRequest 来获取包含动态内容的 DOM
- 提前键入.js在远程 url 中包含动态变量
- URL中包含动态参数的快速路由
- 打印包含动态图像的Div
- 在Bootstrap网站中包含动态/移动背景
- 打开包含动态javascript内容的新窗口
- 如何在javascript中匹配包含动态组件的字符串
- 获取包含动态路径的文件路径
- 在grunt-concat构建步骤中包含动态生成的文件名
- 这是IE8的一个bug吗?table.rows不包含动态生成的表
- 如何发送包含动态html内容的电子邮件
- 包含动态内容的团队页面 - 需要帮助使用 JQuery 拉取图像内容