原生JS實現(xiàn)動態(tài)批量加載js文件


有的時候需要動態(tài)加載javascript文件,并且在加載成功后執(zhí)行回調(diào)函數(shù)舞蔽。要實現(xiàn)這樣的功能,可以使用<script> 元素的load事件(IE9+申屹、chrome焙贷、FireFox等)和onreadystatechange 事件(IE8以下)

當你只需要加載一個js文件時拍皮,可以使用這段代碼:

function loadScript(src, callback) {
    var script = document.createElement('script'),
        head = document.getElementsByTagName('head')[0];
    script.type = 'text/javascript';
    script.charset = 'UTF-8';
    script.src = src;
    if (script.addEventListener) {
        script.addEventListener('load', function () {
            callback();
        }, false);
    } else if (script.attachEvent) {
        script.attachEvent('onreadystatechange', function () {
            var target = window.event.srcElement;
            if (target.readyState == 'loaded') {
                callback();
            }
        });
    }
    head.appendChild(script);
}

//調(diào)用
loadScript('http://cdn.staticfile.org/jquery/1.6.2/jquery.min.js',function(){
    console.log('onload');
});

當你需要加載多個js文件時:

function loadScript(src, callback) {
    arraySync(function (one, i, c) {
        var cur_script = document.createElement("script");
        cur_script.type = 'text/javascript';
        cur_script.charset = 'UTF-8';
        cur_script.src = one;
        cur_script.addEventListener('load', function () {
            c(0, {
                i: i,
                v: {}
            });
        }, false);
        document.head.appendChild(cur_script)
    }, src, function (err, r) {
        //全部加載完成后執(zhí)行的回調(diào)函數(shù)
        if (err) {
            dhtmlxAlert(err.message);
        } else {
            callback()
        }
    });
}

//處理異步歹叮,不用promise的方案
function arraySync(bsFunc, ar) {
    var callback = arguments[arguments.length - 1];
    if (ar.length == 0) {
        callback(0, []);
        return;
    }
    var sendErr = false;
    var finishNum = ar.length;
    var result = [];
    var args = [0, 0];
    for (var index = 2; index < arguments.length - 1; ++index) {
        args.push(arguments[index]);
    }
    args.push(function (err, r) {
        if (err) {
            if (!sendErr) {
                sendErr = true;
                callback(err);
            }
            return;
        }
        --finishNum;
        result[r.i] = r.v;
        if (finishNum == 0) {
            callback(0, result);
        }
    });

    for (var i = 0; i < ar.length; ++i) {
        args[0] = ar[i];
        args[1] = i;
        bsFunc.apply(null, args);
    }
};

//調(diào)用
loadScript(['./jquery.min.js','./echarts.min.js','./vue.min.js'],function(){
    console.log('onload');
});

上述代碼使用了arraySync方案來處理異步,如果條件允許铆帽,你也可以使用promise來解決咆耿,效果都是一樣的。

我的項目中是需要從json文件中讀取配置爹橱,取到的數(shù)據(jù)中有需要動態(tài)加載的js列表萨螺,然后使用上述的批量加載js函數(shù)進行處理,下面給出整體代碼愧驱,有需要的可以搭配使用哦~

var loadScript = function (callback) {
    //讀取json
    var request = new XMLHttpRequest();
    request.open("get", "package.json");
    request.send(null);
    request.onload = function () {
        if (request.status == 200) {
            var package = JSON.parse(request.responseText);
            //合并dependencies和plugins對象
            Object.assign(package.dependencies, package.plugins);
            var scriptUrls = [];
            for (var i in package.dependencies) {
                scriptUrls.push(package.dependencies[i])
            }
            //異步載入script
            arraySync(function (one, i, c) {
                var cur_script = document.createElement("script");
                cur_script.type = 'text/javascript';
                cur_script.charset = 'UTF-8';
                cur_script.src = one;
                cur_script.addEventListener('load', function () {
                    c(0, {
                        i: i,
                        v: {}
                    });
                }, false);
                document.head.appendChild(cur_script)
            }, scriptUrls, function (err, r) {
                if (err) {
                    dhtmlxAlert(err.message);
                } else {
                    callback()
                }
            });
        }
    }
}

//處理異步慰技,不用promise的方案
function arraySync(bsFunc, ar) {
    var callback = arguments[arguments.length - 1];
    if (ar.length == 0) {
        callback(0, []);
        return;
    }
    var sendErr = false;
    var finishNum = ar.length;
    var result = [];
    var args = [0, 0];
    for (var index = 2; index < arguments.length - 1; ++index) {
        args.push(arguments[index]);
    }
    args.push(function (err, r) {
        if (err) {
            if (!sendErr) {
                sendErr = true;
                callback(err);
            }
            return;
        }
        --finishNum;
        result[r.i] = r.v;
        if (finishNum == 0) {
            callback(0, result);
        }
    });

    for (var i = 0; i < ar.length; ++i) {
        args[0] = ar[i];
        args[1] = i;
        bsFunc.apply(null, args);
    }
};
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市组砚,隨后出現(xiàn)的幾起案子吻商,更是在濱河造成了極大的恐慌,老刑警劉巖糟红,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件艾帐,死亡現(xiàn)場離奇詭異,居然都是意外死亡改化,警方通過查閱死者的電腦和手機掩蛤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陈肛,“玉大人,你說我怎么就攤上這事兄裂【浜担” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵晰奖,是天一觀的道長谈撒。 經(jīng)常有香客問我,道長匾南,這世上最難降的妖魔是什么啃匿? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上溯乒,老公的妹妹穿的比我還像新娘夹厌。我一直安慰自己,他們只是感情好裆悄,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布矛纹。 她就那樣靜靜地躺著,像睡著了一般光稼。 火紅的嫁衣襯著肌膚如雪或南。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天艾君,我揣著相機與錄音采够,去河邊找鬼。 笑死冰垄,一個胖子當著我的面吹牛蹬癌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播播演,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼冀瓦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了写烤?” 一聲冷哼從身側(cè)響起翼闽,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎洲炊,沒想到半個月后感局,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡暂衡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年询微,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狂巢。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡撑毛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出唧领,到底是詐尸還是另有隱情藻雌,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布斩个,位于F島的核電站胯杭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏受啥。R本人自食惡果不足惜做个,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一鸽心、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧居暖,春花似錦顽频、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至跟束,卻和暖如春莺奸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背冀宴。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工灭贷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人略贮。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓甚疟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親逃延。 傳聞我的和親對象是個殘疾皇子览妖,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,103評論 1 32
  • # 模塊機制 node采用模塊化結(jié)構(gòu),按照CommonJS規(guī)范定義和使用模塊揽祥,模塊與文件是一一對應關(guān)系讽膏,即加載一個...
    RichRand閱讀 2,508評論 0 3
  • 你不知道JS:異步 第三章:Promises 在第二章,我們指出了采用回調(diào)來表達異步和管理并發(fā)時的兩種主要不足:缺...
    purple_force閱讀 2,068評論 0 4
  • 弄懂js異步 講異步之前拄丰,我們必須掌握一個基礎知識-event-loop府树。 我們知道JavaScript的一大特點...
    DCbryant閱讀 2,711評論 0 5
  • 上一章介紹了模塊的語法,本章介紹如何在瀏覽器和 Node 之中加載 ES6 模塊料按,以及實際開發(fā)中經(jīng)常遇到的一些問題...
    emmet7life閱讀 2,754評論 0 1