2011-11-06 13 views
11

मुझे किसी अन्य जेएस फ़ाइल के अंदर बाहरी जेएस फ़ाइल से जावास्क्रिप्ट फ़ंक्शन का उपयोग करने की आवश्यकता है। यह मूल रूप से कोड मैं कोशिश की है है:क्या मैं कॉलबैक के बिना jquery getScript() का उपयोग कर सकता हूं?

$.getScript('js/myHelperFile.js'); 
myHelperFunction(); 

यह काम नहीं करता है - मैं की "myHelperFunction परिभाषित नहीं है" कोई त्रुटि मिलती है।

हालांकि, इस कोड काम करता है:

$.getScript('js/myHelperFile.js', function(){myHelperFunction();}); 

मैं विशेष रूप से यह पहला तरीका ऐसा करने में सक्षम होना चाहता हूँ - मेरी फाइल के शीर्ष पर फ़ाइल को लोड, और फिर किसी भी कार्य करता है मैं वहाँ पर से जरूरत का उपयोग । क्या यह संभव है, या क्या मैं गलत समझ रहा हूं कि स्क्रिप्टस्क्रिप्ट कैसे काम करता है?

उत्तर

29

इसे "पहला तरीका" वर्तमान में *jQuery.getScript के साथ संभव नहीं है क्योंकि यह केवल एसिंक्रोनस ऑपरेशंस का समर्थन करता है, और इस प्रकार इसे कॉल करने के तुरंत बाद लौटाता है।

जब स्क्रिप्ट myHelperFunction(), myHelperFunction को undefined का आह्वान करने का प्रयास करता है तो यह आपकी स्क्रिप्ट डाउनलोड होने से पहले लौटाता है और उस त्रुटि का कारण बनता है।

*एक आशाजनक नई विधि के लिए इस उत्तर के निचले हिस्से में अद्यतन देखें जो अंततः आपको वांछित शैली की तरह काम करने वाले कोड लिखने की अनुमति देगा।

आप async सेटिंग कोड के साथ false करने के लिए सेट कुछ इस तरह है कि साथ jQuery.ajax का उपयोग कर इसे कर सकता है:

$.ajax({ 
    url: 'js/myHelperFile.js', 
    async: false, 
    dataType: "script", 
}); 

myHelperFunction(); 

documentation राज्यों के रूप में लेकिन:

सिंक्रोनस अनुरोध कर सकते हैं अनुरोध सक्रिय होने पर किसी भी क्रिया को अक्षम करने, ब्राउज़र को अस्थायी रूप से लॉक कर दें।

यह एक बहुत ही बुरी बात है। यदि myHelperFile.js प्रदान करने वाला सर्वर किसी भी समय प्रतिक्रिया देने में धीमा है ( कुछ बिंदु पर होगा) पृष्ठ समाप्त होने या समय-समय पर पृष्ठ उत्तरदायी नहीं होगा।

कॉलबैक शैली को गले लगाने के लिए यह एक बेहतर विचार होगा जो पूरे jQuery में भारी रूप से उपयोग किया जाता है।

$.getScript('js/myHelperFile.js', function() { 
    myHelperFunction(); 
}); 

आप या तो एक गुमनाम समारोह का उपयोग करने की जरूरत नहीं आप एक नामित समारोह में अपने कोड डाल सकते हैं:

function doStuffWithHelper() { 
    myHelperFunction(); 
} 

$.getScript('js/myHelperFile.js', doStuffWithHelper); 

आप कॉल करने से पहले एक से अधिक निर्भरता लोड करने के लिए की जरूरत है myHelperFunction यह तब तक काम नहीं करेगा जब तक कि आप किसी भी प्रकार की प्रणाली सेट अप नहीं करते हैं, यह पता लगाने के लिए कि क्या आपकी सभी निर्भरताएं आपके कोड को निष्पादित करने से पहले डाउनलोड की गई हैं। इसके बाद आप .getScript कॉल पर कॉलबैक हैंडलर सेट कर सकते हैं ताकि यह पता चल सके कि आपकी सभी निर्भरताएं आपके कोड को चलाने से पहले लोड की गई हैं।

var loadedScripts = { 
    myHelperFile: false, 
    anotherHelperFile: false 
}; 

function doStuffWithHelper() { 
    // check to see if all our scripts are loaded 
    var prop; 
    for (prop in loadedScripts) { 
     if (loadedScripts.hasOwnProperty(prop)) { 
      if (loadedScripts[prop] === false) { 
       return; // not everything is loaded wait more 
      } 
     } 
    } 

    myHelperFunction(); 
} 

$.getScript('js/myHelperFile.js', function() { 
    loadedScripts.myHelperFile = true; 
    doStuffWithHelper(); 
}); 
$.getScript('js/anotherHelperFile.js', function() { 
    loadedScripts.anotherHelperFile = true; 
    doStuffWithHelper(); 
}); 

आप देख सकते हैं, दृष्टिकोण इस तरह की घुमावदार और unmaintainable तेजी से हो जाता है।

यदि आपको एकाधिक निर्भरताओं को लोड करने की आवश्यकता है तो आप इसे करने के लिए yepnope.js जैसे स्क्रिप्टलोडर का उपयोग करना बेहतर होगा।

yepnope({ 
     load : [ 'js/myHelperFile.js', 'js/anotherHelperFile.js' ], 
     complete: function() { 
      var foo; 
      foo = myHelperFunction(); 
      foo = anotherHelperFunction(foo); 
      // do something with foo 
     } 
}); 

Yepnope कॉलबैक का उपयोग करता है बस .getScript ताकि आप अनुक्रमिक शैली आप के साथ रहना चाहता था उपयोग नहीं कर सकते हैं। यह एक अच्छा ट्रेडऑफ है हालांकि एक पंक्ति में एकाधिक सिंक्रोनस jQuery.ajax कॉल करने से केवल उन तरीकों की समस्याएं मिलती हैं।


अद्यतन 2013-12-08

jQuery 1.5 release, यह ऐसा करने का एक और शुद्ध jQuery तरीका प्रदान करता है। 1.5 के रूप में, सभी AJAX अनुरोध वापसी एक Deferred Object तो आप ऐसा कर सकते हैं:

$.getScript('js/myHelperFile.js').done(function() { 
    myHelperFunction(); 
}); 

एक अतुल्यकालिक अनुरोध होने के नाते, निश्चित रूप से यह एक कॉलबैक की आवश्यकता है।का उपयोग करते हुए Deferreds हालांकि, पारंपरिक कॉलबैक प्रणाली पर एक बहुत बड़ा फायदा है $.when() का उपयोग कर आप आसानी से अपने खुद जटिल ट्रैकिंग प्रणाली के बिना एक से अधिक शर्त स्क्रिप्ट लोड हो रहा है करने के लिए इस विस्तार कर सकते हैं:

$.when($.getScript('js/myHelperFile.js'), $.getScript('js/anotherHelperFile.js')).done(function() { 
    var foo; 
    foo = myHelperFunction(); 
    foo = anotherHelperFunction(foo); 
    // do something with foo 
}); 

यह दोनों लिपियों एक साथ डाउनलोड हूं और मैं केवल कॉलबैक पर अमल दोनों के बाद डाउनलोड किया गया था, ऊपर Yepnope उदाहरण की तरह।


अद्यतन 2014-03-30

मैं हाल ही में an article पढ़ा है कि मुझे एक नया जावास्क्रिप्ट विशेषता यह है कि भविष्य में हो सकता है प्रक्रियात्मक दिखने में अभी तक async कोड की तरह सक्षम से अवगत कराया है कि आप उपयोग करना चाहते थे! Async Functions एक async समारोह के निष्पादन को रोकने के लिए जब तक अतुल्यकालिक आपरेशन पूरा करता await कीवर्ड का उपयोग करेगा। बुरी खबर यह है कि वर्तमान में यह ईएस 7, दो ईसीएमएस्क्रिप्ट संस्करणों को दूर करने के लिए तैयार है।

await एसिंक्रोनस फ़ंक्शन पर निर्भर करता है जो आप Promise लौटने पर प्रतीक्षा कर रहे हैं। मुझे यकीन है कि कैसे ब्राउज़र कार्यान्वयन व्यवहार करेंगे नहीं कर रहा हूँ अगर वे एक सच्चे ES6 वादा वस्तु की आवश्यकता होगी या यदि AJAX से एक jQuery रिटर्न की तरह वादों की अन्य कार्यान्वयन कॉल पर्याप्त होगा।

"use strict"; 
var getScript = function (url) { 
    return new Promise(function(resolve, reject) { 
    jQuery.getScript(url).done(function (script) { 
     resolve(script); 
    }); 
    }); 
}; 
आगे बढ़ने से पहले

तो आप इसे डाउनलोड करने के लिए उपयोग कर सकते हैं और await:

(async function() { 
    await getScript('js/myHelperFile.js'); 
    myHelperFunction(); 
}()); 

आप कर रहे हैं एक ES6 वादा आवश्यकता है, तो आप एक समारोह है कि एक वादा रिटर्न के साथ jQuery.getScript रैप करने के लिए की आवश्यकता होगी वास्तव में आज इस शैली में लिखने के लिए आपको asyc और await उपयोग कर सकते हैं और फिर Traceur का उपयोग करें कि वर्तमान ब्राउज़रों में चलेंगे कोड में अपने कोड transpile के लिए निर्धारित किया। ऐसा करने के अतिरिक्त लाभ यह है कि आप भी कई other useful new ES6 features भी इस्तेमाल कर सकते हैं है।

+0

आश्चर्यजनक व्यापक जवाब है, अच्छी तरह से किया! – GregL

+0

+! काफी पूरा जवाब। Howerever, अगर आप jQuery के लोड होने पर 'for..in' synthax के साथ क्यों चल रहे हैं? –

+0

@ gion_13 यह मुझे फ़ंक्शन से बाहर निकलने के लिए {if (loadedScripts [prop] === false) {'के अंदर से वापस आने की अनुमति देता है ताकि निर्भरता पर निर्भर होने वाला निम्न कोड नहीं चल सके। अगर मैंने '$ .each 'का उपयोग किया, तो मैं लूप को' वापसी झूठी 'के साथ जल्दी से रोक सकता था लेकिन फिर लूप के बाद कोड चलाएगा, मुझे लूप से पहले किसी प्रकार का झंडा सेट करना होगा और फिर लूप के बाद इसे जांचना होगा उस कोड को चलने से रोकने के लिए। 'For..in' लूप का उपयोग करना और फ़ंक्शन से बाहर निकलना क्लीनर है। इसे अभी देखकर, शब्दकोश के बजाय मैं सिर्फ एक गिनती var का उपयोग करता था और इसके बजाय कुल स्क्रिप्ट पर इसकी तुलना करता था। –

2

getScript() फ़ंक्शन का उपयोग करके, मुझे नहीं लगता कि आप कर सकते हैं। समस्या यह है कि स्क्रिप्ट को AJAX का उपयोग करके लोड किया जा रहा है (वास्तव में, getScript एक विशेष $.ajax() फ़ंक्शन के लिए केवल एक शॉर्टेंड है), और जब ब्राउज़र अगली पंक्ति पर फ़ंक्शन निष्पादित करने का प्रयास करता है, तो शायद सर्वर ने फ़ाइल को वापस नहीं किया है।

आप एक कॉलबैक फ़ंक्शन का उपयोग नहीं करना चाहते हैं, तो आप अपने मूल रूप में jQuery $.ajax() समारोह का उपयोग करने के (getScript() के बारे में भूल जाते हैं और) के रूप में तुल्यकालिक हस्तांतरण सेट की आवश्यकता होगी, और। इस तरह, आप सुनिश्चित करें कि स्क्रिप्ट अपने कोड के निष्पादन से पहले लोड किया जाएगा हो सकता है जारी है:

$.ajax({ 
    url: url, 
    dataType: "script", 
    async: false 
}); 
2

$ .getScript, और वास्तव में सभी HTTP ओपी संबंधित jQuery कार्यों डिफ़ॉल्ट रूप से गैर-अवरुद्ध कॉल कर रहे हैं। यही कहना है कि ऑपरेशन पूरा होने पर कोड लटका नहीं है। इसका अर्थ यह है कि उपर्युक्त आपका कोड निश्चित रूप से असफल हो जाएगा क्योंकि ऐसा कोई तरीका नहीं है कि $ .getScript स्क्रिप्ट को निष्पादित करने की कोशिश करने वाली लाइन से पहले स्क्रिप्ट लोड करेगा। यही कारण है कि कॉलबैक फ़ंक्शन पैरामीटर के रूप में स्वीकार किए जाते हैं।

हालांकि, आप जो करने की कोशिश कर रहे हैं वह संभव है। एक बार स्क्रिप्ट लोड हो जाने के बाद आपको इसे कहीं से भी कॉल करने में सक्षम होना चाहिए। डाउनलोड की जाने वाली स्क्रिप्ट से पहले बुलाए जाने वाले तरीके से बचने के लिए आवश्यक सभी आवश्यक झंडे सेट कर रहे हैं।

var HelperFileLoaded = false; 
$.getScript('js/myHelperFile.js', function() { HelperFileLoaded = true; }); 

// ... 

function btnSaveClick() { 
    if(!HelperFileLoaded) return; 
    myHelperFunction(); 
} 

BenM के सुझाव संभव है लेकिन जब तक आप केवल एक ही कॉल करते समय myHelperFunction के लिए यह एक समाधान के रूप काम नहीं करेगा क्योंकि कोई गारंटी नहीं कि स्क्रिप्ट से पहले किसी भी अन्य तरीकों myHelperFunction बुला है डाउनलोड किया है जाएगा ट्रिगर किया गया

0

आपका पहले एक ठीक काम करता है अगर आप JSONP का उपयोग कर रहे हैं, मैं इसे उस तरह से अक्सर करते हैं।

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