क्या मैं पूरा पृष्ठ लोड होने से पहले जावास्क्रिप्ट चला सकता हूँ?


96

मैं पूरे पृष्ठ को लोड करने से पहले थोड़ी जावास्क्रिप्ट चलाना चाहता हूं। क्या यह संभव है? या कोड निष्पादित करना शुरू करता है </html>?



2
मुझे नहीं लगता कि यह एक डुप्लिकेट है - इसके सर्वर-क्लाइंट संचार प्रश्न का अधिक है।
स्क्यूलिफ

जवाबों:


186

इतना ही नहीं कर सकते हैं आप, लेकिन आप एक विशेष प्रयास करने की आवश्यकता नहीं है, तो आप के लिए नहीं करना चाहते हैं। :-)

जब ब्राउज़र scriptHTML को पार्स करते समय एक क्लासिक टैग का सामना करता है , तो यह पार्स करना बंद कर देता है और जावास्क्रिप्ट दुभाषिया को सौंप देता है, जो स्क्रिप्ट चलाता है। जब तक स्क्रिप्ट का निष्पादन पूरा नहीं हो जाता है तब तक पार्सर जारी नहीं होता (क्योंकि स्क्रिप्ट document.writeआउटपुट मार्कअप को कॉल कर सकती है जिसे पार्सर को संभालना चाहिए)।

यह डिफ़ॉल्ट व्यवहार है, लेकिन स्क्रिप्ट निष्पादन में देरी के लिए आपके पास कुछ विकल्प हैं:

  1. जावास्क्रिप्ट मॉड्यूल का उपयोग करें। जब तक HTML पूरी तरह से पार्स नहीं किया गया है और प्रारंभिक DOM बनाया गया है तब तक एक type="module"स्क्रिप्ट आस्थगित है । यह मॉड्यूल का उपयोग करने का प्राथमिक कारण नहीं है, लेकिन यह एक कारण है:

    <script type="module" src="./my-code.js"></script>
    <!-- Or -->
    <script type="module">
    // Your code here
    </script>
    

    कोड प्राप्त किया जाएगा (यदि यह अलग है) और HTML पार्सिंग के साथ समानांतर में पार्स किया गया है, लेकिन HTML पार्सिंग होने तक नहीं चलाया जाएगा । (यदि आपका मॉड्यूल कोड स्वयं की फ़ाइल के बजाय इनलाइन है, तो इसे HTML पार्सिंग पूर्ण होने तक भी टाल दिया जाता है।)

    यह उपलब्ध नहीं था जब मैंने पहली बार 2010 में यह उत्तर लिखा था, लेकिन 2020 में, सभी प्रमुख आधुनिक ब्राउज़र मूल रूप से मॉड्यूल का समर्थन करते हैं, और यदि आपको पुराने ब्राउज़रों का समर्थन करने की आवश्यकता है, तो आप वेबपैक और रोलअप.जैस जैसे बंडल का उपयोग कर सकते हैं।

  2. deferएक क्लासिक स्क्रिप्ट टैग पर विशेषता का उपयोग करें :

    <script defer src="./my-code.js"></script>

    मॉड्यूल के साथ के रूप में, कोड प्राप्त किया my-code.jsजाएगा और HTML पार्सिंग के साथ समानांतर में पार्स किया जाएगा, लेकिन जब तक HTML पार्स नहीं किया जाता है तब तक इसे चलाया नहीं जाएगा । लेकिन , deferइनलाइन स्क्रिप्ट सामग्री के साथ काम नहीं करता, केवल बाहरी फ़ाइलों के माध्यम से संदर्भित करता है src

  3. मुझे नहीं लगता कि आप क्या चाहते हैं, लेकिन आप asyncHTML पार्सिंग के साथ जावास्क्रिप्ट कोड लाने के लिए ब्राउज़र को बताने के लिए विशेषता का उपयोग कर सकते हैं , लेकिन फिर इसे जल्द से जल्द चलाएं, भले ही HTML पार्सिंग पूरी न हो । आप इसे एक type="module"टैग पर रख सकते हैं , या deferएक क्लासिक scriptटैग के बजाय इसका उपयोग कर सकते हैं ।

  4. scriptटैग को दस्तावेज़ के अंत में रखें , केवल समापन </body>टैग से पहले :

    <!doctype html>
    <html>
    <!-- ... -->
    <body>
    <!-- The document's HTML goes here -->
    <script type="module" src="./my-code.js"></script><!-- Or inline script -->
    </body>
    </html>
    

    इस तरह, भले ही कोड को उसके सामने आते ही चलाया जाता है, लेकिन इसके ऊपर HTML द्वारा परिभाषित सभी तत्व मौजूद हैं और उपयोग करने के लिए तैयार हैं।

    ऐसा हुआ करता था कि इसने कुछ ब्राउज़रों पर एक अतिरिक्त विलंब का कारण बना क्योंकि वे कोड को तब तक प्राप्त नहीं करना चाहते थे जब तक कि scriptटैग का सामना नहीं किया जाता है, लेकिन आधुनिक ब्राउज़र आगे स्कैन करते हैं और प्रीफ़ेट करना शुरू करते हैं। फिर भी, यह इस बिंदु पर तीसरी पसंद है, दोनों मॉड्यूल और deferबेहतर विकल्प हैं।

कल्पना एक उपयोगी आरेख है एक कच्चे दिखा scriptटैग, defer, async, type="module", और type="module" asyncऔर जब जावा स्क्रिप्ट कोड प्राप्त किए गए और रन है के समय:

यहां छवि विवरण दर्ज करें

यहां डिफ़ॉल्ट व्यवहार का एक उदाहरण है, एक कच्चा scriptटैग:

.found {
    color: green;
}
<p>Paragraph 1</p>
<script>
    if (typeof NodeList !== "undefined" && !NodeList.prototype.forEach) {
        NodeList.prototype.forEach = Array.prototype.forEach;
    }
    document.querySelectorAll("p").forEach(p => {
        p.classList.add("found");
    });
</script>
<p>Paragraph 2</p>

( उस कोड के आसपास के विवरण के लिए मेरा जवाब यहां देखें NodeList।)

जब आप उसे चलाते हैं, तो आप "पैरा 1" को हरे रंग में देखते हैं लेकिन "पैरा 2" काला है, क्योंकि स्क्रिप्ट HTML पार्सिंग के साथ समान रूप से चलती है, और इसलिए यह केवल पहला पैराग्राफ पाया, दूसरा नहीं।

इसके विपरीत, यहाँ एक type="module"स्क्रिप्ट है:

.found {
    color: green;
}
<p>Paragraph 1</p>
<script type="module">
    document.querySelectorAll("p").forEach(p => {
        p.classList.add("found");
    });
</script>
<p>Paragraph 2</p>

ध्यान दें कि वे दोनों अब कैसे हरे हैं; HTML पार्सिंग पूर्ण होने तक कोड नहीं चला। यह defer scriptबाहरी सामग्री (लेकिन इनलाइन सामग्री नहीं) के साथ भी सच होगा ।

(वहां NodeListचेक की कोई आवश्यकता नहीं थी क्योंकि किसी भी आधुनिक ब्राउज़र सहायक मॉड्यूल पहले से मौजूद forEachहैं NodeList।)

इस आधुनिक दुनिया में, DOMContentLoaded"रेडी" फीचर की घटना का कोई वास्तविक मूल्य नहीं है , जो कि प्रोटोटाइपोटाइप्स, jQuery, एक्सटीजेएस, डोजो, और अधिकांश अन्य ने दिन में वापस प्रदान किया (और अभी भी प्रदान करते हैं); बस मॉड्यूल का उपयोग करें या defer। वापस यहां तक कि दिन में, वहाँ उन्हें प्रयोग करने के बहुत ज्यादा नहीं कारण था (और वे अक्सर पेज प्रस्तुति जबकि पूरे jQuery पुस्तकालय क्योंकि लोड किया गया था को पकड़े गलत तरीके से इस्तेमाल किया गया, scriptमें किया गया था headके बजाय दस्तावेज़ के बाद), कुछ पर कुछ डेवलपर्स Google ने जल्द ही हरी झंडी दिखा दी। यह वाईयूआई की सिफारिश के कारण भी था , जो स्क्रिप्ट के अंत में body, फिर से दिन में वापस लाने के लिए था।


1
@FeRD - संपादन के लिए धन्यवाद। समीक्षकों ने इसे अस्वीकार कर दिया, लेकिन आप काफी सही थे। :-)
टीजे क्राउडर

या यह सब एक समारोह में डाल दिया और इसे में डाल दिया <body onload="doIt()>"
जस्टिन लियू

@JustinLiu - loadघटना पृष्ठ लोड चक्र में बहुत देर से होती है, यह तब तक अपने जावास्क्रिप्ट को चलाने के लिए इंतजार करने के लिए लगभग सबसे अच्छा अभ्यास नहीं है। लेकिन हां, यह एक विकल्प है। मैंने 2020 के उत्तर के लिए ओवरहॉल किया है, btw।
टीजे क्राउडर

या आप का उपयोग कर सकते हैंdocument.addEventListener('DOMContentLoaded', function(){ //doyour stuff })
जस्टिन लियू

@JustinLiu - हाँ, अंतिम पैराग्राफ देखें। :-) मैंने कभी कोई ज़रूरत नहीं देखी, लेकिन आप कर सकते हैं।
टीजे क्राउडर

6

आप किसी भी समय जावास्क्रिप्ट कोड चला सकते हैं। AFAIK को उसी क्षण निष्पादित किया जाता है जब ब्राउज़र <script> टैग पर पहुंचता है जहां यह है। लेकिन आप उन तत्वों तक नहीं पहुंच सकते जो अभी तक लोड नहीं किए गए हैं।

इसलिए यदि आपको तत्वों तक पहुंच की आवश्यकता है, तो आपको तब तक इंतजार करना चाहिए जब तक कि डोम लोड न हो जाए (इसका मतलब यह नहीं है कि पूरा पृष्ठ छवियों और सामानों से भरा हुआ है। यह केवल दस्तावेज की संरचना है, जो बहुत पहले लोड हो गया है, इसलिए आप आमतौर पर जीते हैं। jQuery की DOMContentLoadedतरह ईवेंट या फ़ंक्शंस का उपयोग करते हुए) एक सूचना पर देरी हो रही $.readyहै।


2
DOMContentLoaded ईवेंट जैसे ही DOM पदानुक्रम पूरी तरह से बन गया है, आग लग जाएगी, लोड घटना तब होगी जब सभी छवियों और उप-फ़्रेमों ने लोडिंग समाप्त कर दी हो।
BeauCielBleu
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.