2012-03-14 8 views
9

में लोड स्क्रिप्ट मैं jQuery के साथ लोड कोशिश कर रहा हूँ कुछ स्क्रिप्ट गतिशील:jQuery: आदेश

var scripts = ['script1.js','script2.js','script3.js']; 

$.each(scripts , function(i, val) { 
    $.getScript(val, function() { 
    console.log('loaded '+ val); 
}); 

लेकिन कभी कभी भरी हुई स्क्रिप्ट का क्रम बदल गया। पिछले एक सफलतापूर्वक लोड होने के बाद मैं प्रत्येक स्क्रिप्ट कैसे लोड कर सकता हूं?

उत्तर

16

आप रिकर्सिव फ़ंक्शन कॉल के रूप में $.getScript() के कॉलबैक फ़ंक्शन का उपयोग कर लोडिंग समाप्त होने के बाद प्रत्येक को लोड कर सकते हैं।

//setup array of scripts and an index to keep track of where we are in the process 
var scripts = ['script1.js','script2.js','script3.js'], 
    index = 0; 

//setup a function that loads a single script 
function load_script() { 

    //make sure the current index is still a part of the array 
    if (index < scripts.length) { 

     //get the script at the current index 
     $.getScript(scripts[index], function() { 

      //once the script is loaded, increase the index and attempt to load the next script 
      console.log('Loaded: ' + scripts[index]); 
      index++; 
      load_script(); 
     }); 
    } 
} 

क्या अपने कोड में होने वाली है कि स्क्रिप्ट एक ही समय में अनुरोध किया जा रहा है और जब से वे अतुल्यकालिक रूप से लोड करते हैं, वे लौट सकते हैं और यादृच्छिक क्रम में निष्पादित।

अद्यतन

मैं इस परीक्षण नहीं किया है, लेकिन अगर स्क्रिप्ट स्थानीय स्तर पर होस्ट किया गया है, तो आप तो, सादे पाठ में उन्हें पुनः प्राप्त जब तक वे सभी जिस पर लोड किए गए हैं चर में कोड के सभी स्टोर करने के लिए कोशिश कर सकते बार जब आप क्रम में स्क्रिप्ट का मूल्यांकन कर सकते हैं:

var scripts = ['script1.js','script2.js','script3.js'], 

    //setup object to store results of AJAX requests 
    responses = {}; 

//create function that evaluates each response in order 
function eval_scripts() { 
    for (var i = 0, len = scripts.length; i < len; i++) { 
     eval(responses[scripts[i]]); 
    } 
} 

$.each(scripts, function (index, value) { 
    $.ajax({ 
     url  : scripts[index], 

     //force the dataType to be `text` rather than `script` 
     dataType : 'text', 
     success : function (textScript) { 

      //add the response to the `responses` object 
      responses[value] = textScript; 

      //check if the `responses` object has the same length as the `scripts` array, 
      //if so then evaluate the scripts 
      if (responses.length === scripts.length) { eval_scripts(); } 
     }, 
     error : function (jqXHR, textStatus, errorThrown) { /*don't forget to handle errors*/ } 
    }); 
}); 
+0

आह, निंजा। हालांकि अच्छा काम है। –

+0

ऐसा लगता है कि काम कर रहा है !, धन्यवाद और बहुत अच्छी व्याख्या! – greenbandit

0

आप सॉर्ट कर सकते हैं() सरणी -

var sorted = scripts.sort(); 

और फिर अपने प्रत्येक कार्य में सॉर्ट का उपयोग करें।

+0

मेरा मानना ​​है कि ओपीएस प्रश्न AJAX अनुरोधों के जवाबों के आदेश के संबंध में है। – Jasper

1

कुछ स्क्रिप्ट आकार में भिन्न हो सकती हैं, इसलिए यह अप्रत्याशित है। इस तरह कुछ कोशिश करो। के बाद पिछले एक पूरी तरह लोड होने

var scripts = ['script1.js','script2.js','script3.js'], ScriptIndex = 0; 
function LoadScript(index){ 
    if(index >= scripts.length) 
     return; 

    $.getScript(scripts[index], function(){ 
     console.log('Loaded script '+ scripts[index]); 
     LoadScript(++ScriptIndex); 
    } 
} 

यह प्रत्येक स्क्रिप्ट लोड करना चाहिए। सुनिश्चित करें कि आप यह कार्यप्रणाली को कॉल करके शुरू LoadScript(0);

+0

'++ स्क्रिप्ट इंडेक्स' और 'स्क्रिप्ट इंडेक्स ++' (यदि कोई है तो) के बीच क्या अंतर है? – Jasper

+0

'+ स्क्रिप्ट इंडेक्स 'सेट, और बढ़ी हुई मान देता है, जबकि' ScriptIndex ++ 'बस बढ़ी हुई मान सेट करता है। –

+1

गोचा, धन्यवाद। – Jasper

10

आप इस तथ्य का उपयोग कर बनाने के jqXhr object$.getScript (और अन्य सभी अजाक्स विधि) द्वारा दिया वादा इंटरफ़ेस लागू करता है और इसलिए .pipe() प्रदान करता है जो श्रृंखला टाल वस्तुओं के लिए इस्तेमाल किया जा सकता :

var deferred = new $.Deferred(), 
    pipe = deferred; 

$.each(scripts , function(i, val) { 
    pipe = pipe.pipe(function() { 
     return $.getScript(val, function() { 
      console.log('loaded '+ val); 
     }); 
    }); 
}); 

deferred.resolve(); 

अधिक जानकारी के लिए deferred objects और deferred.pipe पर एक नजर है।

कुल मिलाकर, स्थगित वस्तुओं का उपयोग करके आप अधिक लचीलापन प्रदान करते हैं और आपको त्रुटि हैंडलर को अधिक आसानी से जोड़ सकते हैं।

+0

चूंकि मैंने स्थगित होने के बारे में सीखा है, इसलिए मैं उन्हें प्यार करता हूं। लेकिन किसी भी तरह से मैंने पाइप सुविधा को याद किया। महान पद! – roberkules

+0

यह बेकार है - आप मूल रूप से '$ कर रहे हैं। जब ($ .getScript (ए), $ .getScript (बी)) '-' स्क्रिप्ट्स 'अभी भी सर्वर से लोड होने के बाद ठीक से eval'd हैं, भले ही पिछले एक को पहले ही डाउनलोड कर लिया गया हो या नहीं। – Dwelle

+0

@Dwellee: नहीं, यह मामला नहीं है। '$ .getScript (बी)' को '.pipe' कॉलबैक के अंदर बुलाया जाता है, जिसे केवल '$ .getScript (ए)' के बाद बुलाया जाता है (चाहे उसका मूल्यांकन किया गया हो, मुझे यकीन नहीं है)। –

2

एक बढ़ाया की @ जैस्पर का समाधान संस्करण:

  • $.when का उपयोग करके कॉल सिंक्रनाइज़ करने के लिए।
  • वैश्विक eval का उपयोग कर।

    /** 
    * Load scripts in parallel keeping execution order. 
    * @param {array} An array of script urls. They will parsed in the order of the array. 
    * @returns {$.Deferred} 
    */ 
    function getScripts(scripts) { 
        var xhrs = scripts.map(function(url) { 
         return $.ajax({ 
          url: url, 
          dataType: 'text', 
          cache: true 
         }); 
        }); 
    
        return $.when.apply($, xhrs).done(function() { 
         Array.prototype.forEach.call(arguments, function(res) { 
          eval.call(this, res[0]); 
         }); 
        }); 
    } 
    

    यह सार: https://gist.github.com/ngryman/7309432

यहाँ कोड है।

संबंधित मुद्दे