วิธีรวมไฟล์ js หลายไฟล์โดยใช้วิธี jQuery $ .getScript ()


127

ฉันกำลังพยายามรวมไฟล์ javascript ลงในไฟล์ js ของฉันแบบไดนามิก ฉันได้ค้นคว้าเกี่ยวกับเรื่องนี้และพบว่าวิธีการ jQuery $ .getScript () น่าจะเป็นวิธีที่ต้องการ

// jQuery
$.getScript('/path/to/imported/script.js', function()
{
    // script is now loaded and executed.
    // put your dependent JS here.
    // what if the JS code is dependent on multiple JS files? 
});

แต่ฉันสงสัยว่าวิธีนี้สามารถโหลดหลายสคริปต์พร้อมกันได้หรือไม่? สาเหตุที่ฉันถามสิ่งนี้เป็นเพราะบางครั้งไฟล์จาวาสคริปต์ของฉันขึ้นอยู่กับไฟล์ js มากกว่าหนึ่งไฟล์

ขอบคุณล่วงหน้า.

คำตอบ:


315

คำตอบคือ

คุณสามารถใช้คำมั่นสัญญาgetScript()และรอจนกว่าสคริปต์ทั้งหมดจะโหลดขึ้นมาเช่น:

$.when(
    $.getScript( "/mypath/myscript1.js" ),
    $.getScript( "/mypath/myscript2.js" ),
    $.getScript( "/mypath/myscript3.js" ),
    $.Deferred(function( deferred ){
        $( deferred.resolve );
    })
).done(function(){
    
    //place your code here, the scripts are all loaded
    
});

ซอ

FIDDLE อีก

ในโค้ดด้านบนการเพิ่ม Deferred และแก้ไขภายใน$()ก็เหมือนกับการวางฟังก์ชั่นอื่น ๆ ในการเรียก jQuery เช่น$(func)มันเหมือนกับ

$(function() { func(); });

กล่าวคือรอให้ DOM พร้อมดังนั้นในตัวอย่างด้านบน$.whenจะรอให้สคริปต์ทั้งหมดถูกโหลดและ DOM จะพร้อมเนื่องจากการ$.Deferredเรียกที่แก้ไขในการเรียกกลับพร้อม DOM


สำหรับการใช้งานทั่วไปฟังก์ชันที่มีประโยชน์

ฟังก์ชันยูทิลิตี้ที่ยอมรับอาร์เรย์ของสคริปต์สามารถสร้างได้ดังนี้:

$.getMultiScripts = function(arr, path) {
    var _arr = $.map(arr, function(scr) {
        return $.getScript( (path||"") + scr );
    });
        
    _arr.push($.Deferred(function( deferred ){
        $( deferred.resolve );
    }));
        
    return $.when.apply($, _arr);
}

ซึ่งสามารถใช้ได้เช่นนี้

var script_arr = [
    'myscript1.js', 
    'myscript2.js', 
    'myscript3.js'
];

$.getMultiScripts(script_arr, '/mypath/').done(function() {
    // all scripts loaded
});

โดยที่พา ธ จะถูกนำหน้าสคริปต์ทั้งหมดและเป็นทางเลือกซึ่งหมายความว่าหากอาร์เรย์มี URL แบบเต็มก็สามารถทำได้เช่นกันและละทิ้งเส้นทางทั้งหมดไว้ด้วยกัน

$.getMultiScripts(script_arr).done(function() { ...

ข้อโต้แย้งข้อผิดพลาด ฯลฯ

นอกจากนี้โปรดทราบว่าการdoneเรียกกลับจะมีอาร์กิวเมนต์จำนวนหนึ่งที่ตรงกับสคริปต์ที่ส่งผ่านโดยแต่ละอาร์กิวเมนต์แสดงอาร์เรย์ที่มีการตอบสนอง

$.getMultiScripts(script_arr).done(function(response1, response2, response3) { ...

[content_of_file_loaded, status, xhr_object]ซึ่งแต่ละอาร์เรย์จะมีสิ่งที่ชอบ โดยทั่วไปเราไม่จำเป็นต้องเข้าถึงอาร์กิวเมนต์เหล่านั้นเนื่องจากสคริปต์จะถูกโหลดโดยอัตโนมัติอยู่แล้วและส่วนใหญ่แล้วการdoneโทรกลับเป็นสิ่งที่เรารู้ว่ามีการโหลดสคริปต์ทั้งหมดแล้วฉันแค่เพิ่มเพื่อความสมบูรณ์ และสำหรับบางครั้งที่หายากเมื่อต้องเข้าถึงข้อความจริงจากไฟล์ที่โหลดหรือเมื่อต้องการเข้าถึงวัตถุ XHR แต่ละชิ้นหรือสิ่งที่คล้ายกัน

นอกจากนี้หากสคริปต์ใดไม่สามารถโหลดได้ระบบจะเรียกตัวจัดการความล้มเหลวและสคริปต์ที่ตามมาจะไม่ถูกโหลด

$.getMultiScripts(script_arr).done(function() {
     // all done
}).fail(function(error) {
     // one or more scripts failed to load
}).always(function() {
     // always called, both on success and error
});

11
ขอบคุณสำหรับคำตอบที่ดี ช่วยอธิบายหน่อยได้ไหมว่าทำไมต้องเพิ่ม$.Deferred(function( deferred ){$( deferred.resolve );})ที่นี่
sozhen

11
อ็อบเจ็กต์ที่รอการตัดบัญชีไม่มีส่วนเกี่ยวข้องกับสัญญาที่ให้คุณโหลดสคริปต์หลาย ๆ สคริปต์และใช้ฟังก์ชันเมื่อเสร็จสิ้นทั้งหมด เพียงแค่ตรวจสอบว่า $ () พร้อมหรือไม่และแก้ไขได้หรือไม่กล่าวอีกนัยหนึ่งก็คือตรวจสอบเพื่อดูว่า DOM พร้อมก่อนที่จะเรียกใช้รหัสใด ๆ เช่นเดียวกับ document. พร้อมแล้วและฉันพบตัวอย่างที่ดีของการแนบ สัญญาว่าจะ getScript ออนไลน์ที่มีฟังก์ชันการทำงานที่พร้อมใช้งาน DOM รอการตัดบัญชีในโค้ดและเพิ่งตัดสินใจที่จะเก็บมันไว้เพราะฟังดูเหมือนเป็นความคิดที่ดี
adeneo

4
นั่นเป็นเพราะการแคชใน ajax ถูกปิดโดยค่าเริ่มต้นใน jQuery เพื่อเปิดและลบสตริงการสืบค้นให้ทำดังนี้ $.ajaxSetup({ cache: true });แต่นั่นอาจส่งผลต่อการโทร ajax อื่น ๆ ที่คุณไม่ต้องการแคชเอกสารสำหรับสิ่งนี้มีมากขึ้นgetScriptและยังมีวิธีการเล็กน้อยในการสร้างฟังก์ชัน getScript ที่เรียกว่า cachedScript
adeneo

3
ขออภัยสำหรับการยอมรับที่ล่าช้า บางครั้งวิธีของคุณก็ยังไม่ค่อยได้ผล ไม่แน่ใจว่าเป็นเพราะสาเหตุใด ฉันพยายามรวมไฟล์สคริปต์สี่ไฟล์พร้อมกัน$.when($.getScript(scriptSrc_1), $.getScript(scriptSrc_2), $.getScript(scriptSrc_3), $.getScript(scriptSrc_4), $.Deferred(function(deferred) { $(deferred.resolve); })).done(function() { ... })
sozhen

1
สำหรับใครก็ตามที่ไม่สามารถใช้งานได้โปรดตรวจสอบว่าไม่มีข้อผิดพลาดในการแยกวิเคราะห์ในไฟล์ JS ของคุณเช่นทดสอบว่าโหลดอย่างถูกต้องในแท็ก <script> ก่อน jQuery.getScript () จะพิจารณาข้อผิดพลาดเหล่านี้ว่าการโหลดล้มเหลวและ .fail () จะถูกเรียกแทน .done () @SongtaoZ
พลังปริซึมของดวงจันทร์

29

ฉันใช้ฟังก์ชันง่ายๆในการโหลดหลายสคริปต์แบบขนาน:

ฟังก์ชัน

function getScripts(scripts, callback) {
    var progress = 0;
    scripts.forEach(function(script) { 
        $.getScript(script, function () {
            if (++progress == scripts.length) callback();
        }); 
    });
}

การใช้

getScripts(["script1.js", "script2.js"], function () {
    // do something...
});

1
ด้วยเหตุผลบางอย่างอันนี้ใช้ได้ดีกว่าของเอ็มมานูเอล เป็นการใช้งานที่โปร่งใสมากเช่นกัน
ทอดด์

@satnam ขอบคุณ :)! คำตอบยอดนิยมใช้ไม่ได้กับบางคน (รวมถึงฉัน) ดังนั้นฉันจึงโพสต์วิธีแก้ปัญหานี้ และดูเรียบง่ายกว่ามาก
Andrei

10

โหลดสคริปต์ที่จำเป็นต่อไปนี้ในการเรียกกลับของก่อนหน้านี้เช่น:

$.getScript('scripta.js', function()
{
   $.getScript('scriptb.js', function()
   {
       // run script that depends on scripta.js and scriptb.js
   });
});

1
แน่นอนวิธีนี้จะดาวน์โหลดสคริปต์ตามลำดับทำให้เวลาในการดำเนินการขั้นสุดท้ายช้าลงหรือไม่?
Jimbo

1
ถูกต้อง @Jimbo - เพื่อความยุติธรรม ควรดำเนินการก่อนกำหนด :)
Alastair

ควรหลีกเลี่ยงน้ำตกเกือบตลอดเวลา getScript มาพร้อมกับคำสัญญา ... คุณสามารถใช้ $. เมื่อรับฟังเมื่อคำสัญญาคลี่คลาย
ร้อยเอ็ด

@Roi และคนอื่น ๆ : ถ้าฉันต้องการสคริปต์เพื่อโหลดในคำสั่งเฉพาะสิ่งที่พูดโดยพื้นฐานผิดกับแนวทางนี้? ดังนั้นทางเลือกที่สัญญาไว้จะได้เปรียบอะไร?
Ifedi Okonkwo

@ ifediOkonkwo สิ่งนี้ใช้งานได้เมื่อพวกเขาต้องอยู่ในซีรีส์ แต่ orig op เพิ่งบอกว่าเขาต้องการทวีคูณพร้อมกัน (ซึ่งจะเป็นการต่อต้านรูปแบบ) ถึงแม้ว่าถ้าฉันต้องการให้เป็นอนุกรมฉันจะเขียนฟังก์ชันวนซ้ำที่ฉันสามารถส่งอาร์เรย์ไปให้ได้ การทำรังลึกจะยุ่งเหยิงอย่างรวดเร็ว
ร้อยเอ็ด

9

บางครั้งจำเป็นต้องโหลดสคริปต์ตามลำดับที่ระบุ ตัวอย่างเช่นต้องโหลด jQuery ก่อน jQuery UI ตัวอย่างส่วนใหญ่ในหน้านี้โหลดสคริปต์แบบขนาน (แบบอะซิงโครนัส) ซึ่งหมายความว่าไม่รับประกันลำดับการดำเนินการ โดยไม่ต้องสั่งซื้อสคริปต์yที่ขึ้นอยู่กับxอาจพังได้หากโหลดทั้งสองสำเร็จ แต่เรียงลำดับไม่ถูกต้อง

ฉันเสนอแนวทางไฮบริดซึ่งอนุญาตให้โหลดตามลำดับของสคริปต์ที่ขึ้นต่อกัน + การโหลดแบบขนานที่เป็นทางเลือก + อ็อบเจ็กต์ที่เลื่อนออกไป :

/*
 * loads scripts one-by-one using recursion
 * returns jQuery.Deferred
 */
function loadScripts(scripts) {
  var deferred = jQuery.Deferred();

  function loadScript(i) {
    if (i < scripts.length) {
      jQuery.ajax({
        url: scripts[i],
        dataType: "script",
        cache: true,
        success: function() {
          loadScript(i + 1);
        }
      });
    } else {
      deferred.resolve();
    }
  }
  loadScript(0);

  return deferred;
}

/*
 * example using serial and parallel download together
 */

// queue #1 - jquery ui and jquery ui i18n files
var d1 = loadScripts([
  "https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js",
  "https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/i18n/jquery-ui-i18n.min.js"
]).done(function() {
  jQuery("#datepicker1").datepicker(jQuery.datepicker.regional.fr);
});

// queue #2 - jquery cycle2 plugin and tile effect plugin
var d2 = loadScripts([
  "https://cdn.rawgit.com/malsup/cycle2/2.1.6/build/jquery.cycle2.min.js",
  "https://cdn.rawgit.com/malsup/cycle2/2.1.6/build/plugin/jquery.cycle2.tile.min.js"

]).done(function() {
  jQuery("#slideshow1").cycle({
    fx: "tileBlind",
    log: false
  });
});

// trigger a callback when all queues are complete
jQuery.when(d1, d2).done(function() {
  console.log("All scripts loaded");
});
@import url("https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/blitzer/jquery-ui.min.css");

#slideshow1 {
  position: relative;
  z-index: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<p><input id="datepicker1"></p>

<div id="slideshow1">
  <img src="https://dummyimage.com/300x100/FC0/000">
  <img src="https://dummyimage.com/300x100/0CF/000">
  <img src="https://dummyimage.com/300x100/CF0/000">
</div>

สคริปต์ในคิวทั้งสองจะดาวน์โหลดพร้อมกันอย่างไรก็ตามสคริปต์ในแต่ละคิวจะดาวน์โหลดตามลำดับเพื่อให้แน่ใจว่ามีการดำเนินการตามลำดับ แผนภูมิน้ำตก:

แผนภูมิน้ำตกของสคริปต์


เราไม่จำเป็นต้องเพิ่มแท็กสคริปต์ใน HTML เมื่อสคริปต์ถูกโหลดในหน่วยความจำหรือไม่?
Ankush Jain

4

ใช้yepnope.jsหรือModernizr (ซึ่งรวมถึง yepnope.js เป็นไฟล์Modernizr.load )

UPDATE

เพื่อติดตามผลต่อไปนี้เป็นสิ่งที่ดีเทียบเท่ากับสิ่งที่คุณใช้อยู่ในปัจจุบันซึ่งแสดงการอ้างอิงในหลายสคริปต์:

yepnope({
  load: ['script1.js', 'script2.js', 'script3.js'],
  complete: function () {
      // all the scripts have loaded, do whatever you want here
  }
});

ขอบคุณ ฉันสามารถใช้หลายตัวyepnope.injectJs( scriptSource )ที่จุดเริ่มต้นของไฟล์ javascript เหมือนกับการรวม<script>แท็กในไฟล์ html ได้หรือไม่
sozhen

นั่นเป็นเรื่องใหม่และจริงๆแล้วฉันไม่เข้าใจว่าทำไมมันถึงต้องการ ทำตามเอกสารด้านล่างเล็กน้อยจากรายการการเปลี่ยนแปลงล่าสุดและคุณจะเห็นการใช้งานทั่วไปมากขึ้น
Chris Pratt

+1; เป็นที่น่าสังเกตว่าเรื่องนี้ต้องจัดการการอ้างอิง (เช่นจะไม่สามารถโหลดสคริปต์เดียวกันสองครั้ง) $.getScriptซึ่งแตกต่างจาก เรื่องนี้ถือเป็นเรื่องใหญ่
OV

yepnope.js คือตอนนี้เลิกใช้
Stephan

4

ฉันพบปัญหาหลายประการเกี่ยวกับการโหลดหลายสคริปต์ซึ่งรวมถึงปัญหาหนึ่งที่ (อย่างน้อยใน Chrome) การโหลดสคริปต์แบบร้อนในโดเมนเดียวกันไม่ทำงานจริงหลังจากที่ Ajax โหลดสำเร็จโดยที่ Cross Domain ทำงานได้ดีอย่างสมบูรณ์! :(

คำตอบที่เลือกสำหรับคำถามเดิมใช้งานไม่ได้อย่างน่าเชื่อถือ

หลังจากการทำซ้ำหลายครั้งนี่คือคำตอบสุดท้ายของฉันสำหรับ getScript และการโหลดสคริปต์หลาย ๆ แบบอะซิงโครนัสตามลำดับที่เข้มงวดโดยเฉพาะโดยมีตัวเลือกการโทรกลับที่โหลดต่อสคริปต์และการโทรกลับโดยรวมเมื่อเสร็จสิ้นทดสอบใน jQuery 2.1+ และ Chrome เวอร์ชันที่ทันสมัย, Firefox และ ละทิ้ง Internet Explorer

กรณีทดสอบของฉันกำลังโหลดไฟล์สำหรับการเรนเดอร์ THREE.JS webGL จากนั้นเริ่มสคริปต์การแสดงผลเมื่อ THREE global พร้อมใช้งานโดยใช้การตรวจสอบช่วงเวลาที่ส่งผ่านไปยังการเรียกใช้ฟังก์ชันแบบไม่ระบุชื่อไปที่ onComplete

ฟังก์ชัน Prototype (getScripts)

function getScripts( scripts, onScript, onComplete )
{
    this.async = true;
    this.cache = false;
    this.data = null;
    this.complete = function () { $.scriptHandler.loaded(); };
    this.scripts = scripts;
    this.onScript = onScript;
    this.onComplete = onComplete;
    this.total = scripts.length;
    this.progress = 0;
};

getScripts.prototype.fetch = function() {
    $.scriptHandler = this;
    var src = this.scripts[ this.progress ];
    console.log('%cFetching %s','color:#ffbc2e;', src);

    $.ajax({
        crossDomain:true,
        async:this.async,
        cache:this.cache,
        type:'GET',
        url: src,
        data:this.data,
        statusCode: {
            200: this.complete
        },
        dataType:'script'
    });
};

getScripts.prototype.loaded = function () {
    this.progress++;
    if( this.progress >= this.total ) {
        if(this.onComplete) this.onComplete();
    } else {
        this.fetch();
    };
    if(this.onScript) this.onScript();
};

วิธีใช้

var scripts = new getScripts(
    ['script1.js','script2.js','script.js'],
    function() {
        /* Optional - Executed each time a script has loaded (Use for Progress updates?) */
    },
    function () {
        /* Optional - Executed when the entire list of scripts has been loaded */
    }
);
scripts.fetch();

ฟังก์ชั่นเป็นไปตามที่ฉันพบโดยใช้ Deferred (เลิกใช้แล้วตอนนี้?) เมื่อใดความสำเร็จและเสร็จสมบูรณ์ในการทดลองของฉันจะไม่น่าเชื่อถือ 100% ดังนั้นฟังก์ชันนี้และการใช้ statusCode เป็นต้น

คุณอาจต้องการเพิ่มพฤติกรรมการจัดการข้อผิดพลาด / ล้มเหลวหากคุณต้องการ


+1 สำหรับการโหลดตามลำดับที่ถูกต้องมักจะสำคัญและบางสิ่งที่คำตอบที่ยอมรับจะไม่รับประกันเว้นแต่ว่าฉันจะพลาดอะไรไป? ฉันได้โพสต์คำตอบสั้น ๆ ที่คล้ายกันไว้ด้านล่าง แต่นี่เป็นกรณีทั่วไป
Whelkaholism

2

คุณสามารถใช้ประโยชน์จาก$.when-method ได้โดยลองใช้ฟังก์ชันต่อไปนี้:

function loadScripts(scripts) {
  scripts.forEach(function (item, i) {
    item = $.getScript(item);
  });
  return $.when.apply($, scripts);
}

ฟังก์ชันนี้จะใช้ในลักษณะนี้:

loadScripts(['path/to/script-a.js', 'path/to/script-b.js']).done(function (respA, respB) {
    // both scripts are loaded; do something funny
});

นั่นคือวิธีการใช้สัญญาและมีค่าใช้จ่ายขั้นต่ำ


สิ่งนี้ทำให้แน่ใจว่าสคริปต์ถูกโหลดตามลำดับหรือไม่
CyberMonk

2

คำตอบที่ดี adeneo

ฉันใช้เวลาสักครู่ในการหาวิธีทำให้คำตอบของคุณเป็นแบบทั่วไปมากขึ้น (เพื่อที่ฉันจะโหลดอาร์เรย์ของสคริปต์ที่กำหนดรหัสได้) การโทรกลับจะถูกเรียกเมื่อสคริปต์ทั้งหมดโหลดและดำเนินการ นี่คือทางออกของฉัน:

    function loadMultipleScripts(scripts, callback){
        var array = [];

        scripts.forEach(function(script){
            array.push($.getScript( script ))
        });

        array.push($.Deferred(function( deferred ){
                    $( deferred.resolve );
                }));

        $.when.apply($, array).done(function(){
                if (callback){
                    callback();
                }
            });
    }

2

ต่อท้ายสคริปต์ด้วย async = false

นี่เป็นวิธีการที่แตกต่าง แต่ง่ายสุด ๆ ในการโหลดสคริปต์หลาย ๆ สคริปต์คุณสามารถผนวกเข้ากับเนื้อหาได้

  • โหลดแบบอะซิงโครนัสเนื่องจากเป็นวิธีที่เบราว์เซอร์เพิ่มประสิทธิภาพการโหลดหน้าเว็บ
  • เรียกใช้สคริปต์ตามลำดับเนื่องจากเป็นวิธีที่เบราว์เซอร์แยกวิเคราะห์แท็ก HTML
  • ไม่จำเป็นต้องโทรกลับเนื่องจากสคริปต์ถูกดำเนินการตามลำดับ เพียงเพิ่มสคริปต์อื่นและจะดำเนินการต่อจากสคริปต์อื่น

ข้อมูลเพิ่มเติมที่นี่: https://www.html5rocks.com/en/tutorials/speed/script-loading/

var scriptsToLoad = [
   "script1.js", 
   "script2.js",
   "script3.js",
]; 
    
scriptsToLoad.forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.body.appendChild(script);
});

1

สิ่งที่คุณกำลังมองหาคือตัวโหลดที่รองรับ AMD (เช่น require.js)

http://requirejs.org/

http://requirejs.org/docs/whyamd.html

มีโอเพ่นซอร์สที่ดีมากมายหากคุณค้นหา โดยทั่วไปจะช่วยให้คุณสามารถกำหนดโมดูลของโค้ดและหากขึ้นอยู่กับโมดูลอื่น ๆ ของโค้ดก็จะรอจนกว่าโมดูลเหล่านั้นจะดาวน์โหลดเสร็จสิ้นก่อนที่จะดำเนินการเรียกใช้ ด้วยวิธีนี้คุณสามารถโหลดโมดูล 10 โมดูลแบบอะซิงโครนัสได้และไม่ควรมีปัญหาแม้ว่าจะขึ้นอยู่กับโมดูลอื่น ๆ ที่จะรันก็ตาม


1

ฟังก์ชันนี้จะตรวจสอบให้แน่ใจว่าไฟล์ถูกโหลดหลังจากโหลดไฟล์อ้างอิงอย่างสมบูรณ์ คุณเพียงแค่ต้องจัดเตรียมไฟล์ตามลำดับโดยคำนึงถึงการพึ่งพาไฟล์อื่น ๆ

function loadFiles(files, fn) {
    if (!files.length) {
        files = [];
    }
    var head = document.head || document.getElementsByTagName('head')[0];

    function loadFile(index) {
        if (files.length > index) {
            var fileref = document.createElement('script');
            fileref.setAttribute("type", "text/javascript");
            fileref.setAttribute("src", files[index]);
            head.appendChild(fileref);
            index = index + 1;
            // Used to call a callback function
            fileref.onload = function () {
                loadFile(index);
            }
        } else if(fn){
            fn();
        }
    }
    loadFile(0);
}

อาจจะดีกว่าคำตอบที่ยอมรับเนื่องจากโหลดไฟล์ตามลำดับ หาก script2 ต้องการให้โหลด script1 การสั่งซื้อเป็นสิ่งสำคัญ
Salman A

1

สิ่งนี้ใช้ได้กับฉัน:

function getScripts(scripts) {
    var prArr = [];
    scripts.forEach(function(script) { 
        (function(script){
            prArr .push(new Promise(function(resolve){
                $.getScript(script, function () {
                    resolve();
                });
            }));
        })(script);
    });
    return Promise.all(prArr, function(){
        return true;
    });
}

และใช้มัน:

var jsarr = ['script1.js','script2.js'];
getScripts(jsarr).then(function(){
...
});

1

นี่คือคำตอบโดยใช้ Maciej Sawicki และใช้งานPromiseเป็นโทรกลับ:

function loadScripts(urls, path) {
    return new Promise(function(resolve) {
        urls.forEach(function(src, i) {

            let script = document.createElement('script');        
            script.type = 'text/javascript';
            script.src = (path || "") + src;
            script.async = false;

            // If last script, bind the callback event to resolve
            if(i == urls.length-1) {                    
                // Multiple binding for browser compatibility
                script.onreadystatechange = resolve;
                script.onload = resolve;
            }

            // Fire the loading
            document.body.appendChild(script);
        });
    });
}

ใช้:

let JSDependencies = ["jquery.js",
                      "LibraryNeedingJquery.js",
                      "ParametersNeedingLibrary.js"];

loadScripts(JSDependencies,'JavaScript/').then(taskNeedingParameters);

ไฟล์ Javascript ทั้งหมดจะถูกดาวน์โหลดโดยเร็วที่สุดและดำเนินการตามลำดับที่กำหนด แล้วtaskNeedingParametersเรียกว่า.


0

คำตอบที่ครอบคลุมของ Andrew Marc Newton ที่สั้นกว่าข้างต้น อันนี้ไม่ได้ตรวจสอบรหัสสถานะสำหรับความสำเร็จซึ่งคุณควรทำเพื่อหลีกเลี่ยงพฤติกรรม UI ที่ไม่ได้กำหนด

อันนี้มีไว้สำหรับระบบที่น่ารำคาญซึ่งฉันสามารถรับประกัน jQuery ได้ แต่ไม่มีอื่น ๆ รวมอยู่ด้วยดังนั้นฉันจึงต้องการเทคนิคที่สั้นพอที่จะไม่ถูกนำไปใช้ในสคริปต์ภายนอกหากถูกบังคับ (คุณสามารถทำให้มันสั้นลงได้โดยการส่งดัชนี 0 ไปยังการเรียก "เรียกซ้ำ" ครั้งแรก แต่ลักษณะนิสัยบังคับทำให้ฉันเพิ่มน้ำตาล)

ฉันยังกำหนดรายการการอ้างอิงให้กับชื่อโมดูลดังนั้นจึงสามารถรวมบล็อกนี้ได้ทุกที่ที่คุณต้องการ "module1" และสคริปต์และการเริ่มต้นที่ขึ้นอยู่กับการเริ่มต้นจะรวม / เรียกใช้เพียงครั้งเดียว (คุณสามารถเข้าสู่ระบบindexการโทรกลับและดูคำสั่งเดียว ชุดของคำขอ AJAX ที่ทำงานอยู่)

if(typeof(__loaders) == 'undefined') __loaders = {};

if(typeof(__loaders.module1) == 'undefined')
{
    __loaders.module1 = false;

    var dependencies = [];

    dependencies.push('/scripts/loadmefirst.js');
    dependencies.push('/scripts/loadmenext.js');
    dependencies.push('/scripts/loadmelast.js');

    var getScriptChain  = function(chain, index)        
    {
        if(typeof(index) == 'undefined')
            index = 0;

        $.getScript(chain[index], 
            function()
            {
                if(index == chain.length - 1)
                {
                    __loaders.module1 = true;

                    /* !!!
                        Do your initialization of dependent stuff here 
                    !!! */
                }
                else 
                    getScriptChain(chain, index + 1);
            }
        );
    };

    getScriptChain(dependencies);       
}

0

มีปลั๊กอินที่ขยายเมธอด getScript ของ jQuery อนุญาตให้โหลดแบบอะซิงโครนัสและซิงโครนัสและใช้กลไกการแคชของ jQuery การเปิดเผยข้อมูลทั้งหมดฉันเขียนสิ่งนี้ โปรดอย่าลังเลที่จะมีส่วนร่วมหากคุณพบวิธีการที่ดีกว่านี้

https://github.com/hudsonfoo/jquery-getscripts


0

โหลดnสคริปต์ทีละรายการ (มีประโยชน์หากตัวอย่างเช่นไฟล์ที่ 2 ต้องการไฟล์ที่ 1):

(function self(a,cb,i){
    i = i || 0; 
    cb = cb || function(){};    
    if(i==a.length)return cb();
    $.getScript(a[i++],self.bind(0,a,cb,i));                    
})(['list','of','script','urls'],function(){console.log('done')});

0

ตามคำตอบจาก @adeneo ด้านบน: รวมทั้งการโหลดไฟล์ css และ js

ข้อเสนอแนะสำหรับการปรับปรุง ??

// Usage
//$.getMultiResources(['script-1.js','style-1.css'], 'assets/somePath/')
//  .done(function () {})
//  .fail(function (error) {})
//  .always(function () {});

(function ($) {
  $.getMultiResources = function (arr, pathOptional, cache) {
    cache = (typeof cache === 'undefined') ? true : cache;
    var _arr = $.map(arr, function (src) {
      var srcpath = (pathOptional || '') + src;
      if (/.css$/i.test(srcpath)) {
        return $.ajax({
          type: 'GET',
          url: srcpath,
          dataType: 'text',
          cache: cache,
          success: function () {
            $('<link>', {
              rel: 'stylesheet',
              type: 'text/css',
              'href': srcpath
            }).appendTo('head');
          }
        });

      } else {
        return $.ajax({
          type: 'GET',
          url: srcpath,
          dataType: 'script',
          cache: cache
        });
      }
    });
    //
    _arr.push($.Deferred(function (deferred) {
      $(deferred.resolve);
    }));
    //
    return $.when.apply($, _arr);
  };
})(jQuery);

0

คุณสามารถลองใช้การเรียกซ้ำ การดำเนินการนี้จะดาวน์โหลดโดยซิงค์ทีละรายการจนกว่าจะดาวน์โหลดรายการทั้งหมดเสร็จสิ้น

var queue = ['url/links/go/here'];

ProcessScripts(function() { // All done do what ever you want

}, 0);

function ProcessScripts(cb, index) {
    getScript(queue[index], function() {
        index++;
        if (index === queue.length) { // Reached the end
            cb();
        } else {
            return ProcessScripts(cb, index);
        }
    });
}

function getScript(script, callback) {
    $.getScript(script, function() {
        callback();
    });
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.