动态包含JavaScript和等待 [英] Dynamically Include JavaScript and Wait

查看:83
本文介绍了动态包含JavaScript和等待的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要做的是动态地包括一个或多​​个JS文件在JavaScript中有什么。我知道有一堆技术这一点,但我正在寻找一个解决方案,遵循以下规则:

1)不使用任何JS框架或库(jQuery的,原型,等等)。

2)的脚本应停止执行,直到外部js文件是完全加载和浏览器解析。

理性背后#2是外部js文件将包括需要被立即使用的脚本被包括在函数定义。在大多数情况下,浏览器还没有来得及解析js文件之前,我开始调用这些功能。

我不介意使用回调知道什么时候脚本加载完成,但是:

1)我不知道提前多少脚本都将被动态包含,所以我不想和不能写一堆嵌套的回调。我只需要知道什么时候他们都装完。

2)我的措辞,试图用某种负荷触发事件,如果浏览器缓存了JavaScript的回调可能无法正常工作。

修改我应该从一开始就提到,这是一个插件系统,但我想保持我的问题/回答足够的通用性是有帮助的其他人。

将用户定义它们希望在数组中要加载的插件。

 插件= ['FooPlugin','BarPlugin'];
 

然后,我会遍历数组,并加载JS脚本为每个插件:

 的(VAR I = 0; I< plugins.length;我++){
    loadScript('插件/+插件[我] +的.js');
}
 

每个插件推本身到loaded_plugins阵列(这是FooPlugin.js的一例)

  load_plugins.push({
    名称:FooPlugin,
    //其他插件的方法和这里的属性
});
 

解决方案

工程跨浏览器的,从IE6。

  document.loadScript =功能(SRC,回调){
    功能脚本(SRC,onload事件){
        VAR scriptTag = document.createElement方法(脚本);
        如果(onload事件)scriptTag.onload = onload事件;
        scriptTag.src = SRC;
        scriptTag.type =文/ JavaScript的;
        返回scriptTag;
    }
    功能外(标签){
        变种D = document.createElement方法('格');
        d.appendChild(标签);
        返回d.innerHTML;
    }
    如果SRC = [来源]((SRC的instanceof阵列)!);
    变种我,可控硅,
        callbackId ='dynCall _'+ Math.floor(的Math.random()* 89999 + 10000);
        计数器= src.length,
        调用=函数(){如果(--counter == 0)回调(); };
    如果(!document.body的){
        窗口[callbackId] =功能(){
            删除窗口[callbackId]
            如果(回调的instanceof功能)回调();
        };
        对于(I = 0; I&其中; src.length;我+ +)的document.write(外(脚本中(src [I])));
        文件撰写('< SCR+IPT类型=文/ JavaScript的>'+'。窗口+ callbackId +'();'+'< / SCR+IPT>');
        返回;
    }
    对于(i = 0; I< src.length;我++)document.body.appendChild(脚本(SRC [我],调用));
};
 

缩小的/模糊的:

 (功能(){document.loadScript =功能(SRC,回调){函数脚本(SRC,onload事件){VAR scriptTag=document.createElement('script');if(onload)scriptTag.onload=onload;scriptTag.src=src;scriptTag.type='text/javascript';return scriptTag}功能外(标签){VAR D = document.createElement方法('格'); d.appendChild(标签);返回d.innerHTML}如果((SRC的instanceof阵列)!)SRC = [来源]; VAR i,scr,callbackId='dynCall_'+Math.floor(Math.random()*89999+10000);counter=src.length,call=function(){if(--counter==0)callback()};if(!document.body){window[callbackId]=function(){delete窗口[callbackId];如果(回调的instanceof Function)callback()};for(i=0;i<src.length;i++)document.write(outer(script(src[i])));document.write('<scr'+'ipt type="text/javascript">'+'window.'+callbackId+'();'+'</scr'+'ipt>');return}for(i=0;i<src.length;i++)document.body.appendChild(script(src[i],call))};document.loadScript.toString=function(){return'function loadScript(){[混淆]}'}})();
 

分支机构的快速解释:

如果script标签调用loadScript是文档头部或身体内,document.body的是不确定的,因为DOM是不是呢。因此,我们不能使用附加标签的标准方法,我们必须用文档写。这具有标签我们写将在一定顺序发生的优势,但我们必须有一个全球范围内的回调函数。缺点

同时,如果我们有document.body的,我们是黄金的做是正确的(-ish - 我们做出牺牲时,有没有图书馆周围,以帮助做是正确的,呃,因此.onload()不过,这是不喜欢我们即将抛出很多事件上的脚本标记,因此它很可能会确定。)缺点(也许?)是脚本所有负载异步的,所以我们需要有一个倒计时运行,因为它们加载

What I'm trying to do is dynamically include one or more js files from within Javascript. I know there are a bunch of techniques for this, but I'm looking for a solution that follows these rules:

1) Not use any JS frameworks or libraries (jQuery, Prototype, etc).

2) The script should halt execution until the external js file is completely loaded and parsed by the browser.

The rational behind #2 is the external js file will include function definitions that need to be used immediately after the script is included. Most of the time the browser hasn't had time to parse the js file before I start calling those functions.

I don't mind using a callback to know when the script is finished loading, but:

1) I don't know ahead of time how many scripts are going to be dynamically included, so I don't want and can't write a bunch of nested callbacks. I just need to know when they're all finished loading.

2) I'm wording that trying to use some kind of "load" event to fire the callback might not work if the browser has cached the JavaScript.

Edit I should have mentioned from the start that this is for a plugin system, but I wanted to keep my question/answer generic enough to be helpful to other people.

Users would define which plugins they want to load in an array.

plugins = [ 'FooPlugin', 'BarPlugin' ];

I would then loop through the array, and load the js script for each plugin:

for(var i = 0; i < plugins.length; i++) {
    loadScript('plugins/' + plugins[i] + '.js');
}

Each plugin pushes itself onto the loaded_plugins array (This is an example of FooPlugin.js)

load_plugins.push({
    name: 'FooPlugin',
    // Other plugin methods and properties here
});

解决方案

Works cross browser, starting with IE6.

document.loadScript = function (src, callback) {
    function script(src, onload) {
        var scriptTag = document.createElement('script');
        if (onload) scriptTag.onload = onload;
        scriptTag.src = src;
        scriptTag.type = 'text/javascript';
        return scriptTag;
    }
    function outer(tag) { 
        var d = document.createElement('div');
        d.appendChild(tag);
        return d.innerHTML;
    }
    if (!(src instanceof Array)) src = [src];
    var i, scr, 
        callbackId = 'dynCall_'+Math.floor(Math.random()*89999+10000);
        counter = src.length, 
        call = function () { if (--counter == 0) callback(); };
    if (!document.body) {
        window[callbackId] = function () {
            delete window[callbackId];
            if (callback instanceof Function) callback();
        };
        for (i=0; i<src.length; i++) document.write(outer(script(src[i])));
        document.write('<scr'+'ipt type="text/javascript">'+'window.'+callbackId+'();'+'</scr'+'ipt>');
        return;
    }
    for (i=0; i<src.length; i++) document.body.appendChild(script(src[i], call));
};

Minified / obfuscated:

(function(){document.loadScript=function(src,callback){function script(src,onload){var scriptTag=document.createElement('script');if(onload)scriptTag.onload=onload;scriptTag.src=src;scriptTag.type='text/javascript';return scriptTag}function outer(tag){var d=document.createElement('div');d.appendChild(tag);return d.innerHTML}if(!(src instanceof Array))src=[src];var i,scr,callbackId='dynCall_'+Math.floor(Math.random()*89999+10000);counter=src.length,call=function(){if(--counter==0)callback()};if(!document.body){window[callbackId]=function(){delete window[callbackId];if(callback instanceof Function)callback()};for(i=0;i<src.length;i++)document.write(outer(script(src[i])));document.write('<scr'+'ipt type="text/javascript">'+'window.'+callbackId+'();'+'</scr'+'ipt>');return}for(i=0;i<src.length;i++)document.body.appendChild(script(src[i],call))};document.loadScript.toString=function(){return'function loadScript() { [obfuscated] }'}})();

Quick explanation of the branches:

If the script tag calling loadScript is within the document head or body, document.body will be undefined, as the DOM isn't in yet. As such, we can't use the standards method of appending a tag, and we must use doc write. This has the advantage that the tags we write will happen in necessarily sequential order, but the disadvantage that we must have a global scope callback function.

Meanwhile, if we have document.body, we're golden for Doing It Right (-ish - we make sacrifices when there's no libraries around to help do it right-er, hence the .onload(). Still, it's not like we're about to throw lots of events on a script tag, so it'll probably be OK.) The disadvantage (maybe?) is that the scripts all load asynchronously, so we need to have a countdown run as they load.

这篇关于动态包含JavaScript和等待的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆