क्या आंतरिक HTML अतुल्यकालिक है?


102

मुझे आशा है कि मैं खुद को मूर्ख नहीं बनाऊंगा लेकिन मैं यह समझने की कोशिश कर रहा हूं कि कोड की उन दो पंक्तियों में क्या हो रहा है:

document.body.innerHTML = 'something';
alert('something else');

मैं जो देख रहा हूं, वह यह है कि HTML अपडेट होने से पहले अलर्ट शो (या हो सकता है कि हो लेकिन पेज रीफ्रेश / रिपीट नहीं हुआ है)

इस कोडपैन को चेकआउट करें कि मेरा क्या मतलब है।

कृपया ध्यान दें कि डालने alertसे भी setTimeout(..., 0)मदद नहीं मिलती है। ऐसा लगता है कि यह innerHTMLवास्तव में पृष्ठ को अपडेट करने के लिए अधिक ईवेंट लूप लेता है ।

संपादित करें:

मैं उल्लेख करना भूल गया कि मैं क्रोम का उपयोग कर रहा हूं और अन्य ब्राउज़रों की जांच नहीं की है। ऐसा लगता है कि यह केवल क्रोम में दिखाई दे रहा है। फिर भी मुझे अभी भी दिलचस्पी है कि ऐसा क्यों हो रहा है।


4
यह क्रोम के लिए विशिष्ट है।
ट्रिनकोट

2
@trincot धन्यवाद! मैं उल्लेख करना भूल गया कि मैं क्रोम का उपयोग कर रहा हूं और पूछने से पहले अन्य ब्राउज़र की कोशिश नहीं की। क्या आपके पास कोई संदर्भ है?
अपाइफॉबार्ट

16
DOM को बदलना तुल्यकालिक है। प्रतिपादन डोम वास्तव में के बाद जावास्क्रिप्ट ढेर को मंजूरी दी है होता है। Developers.google.com/web/fundamentals/performance/rendering जावास्क्रिप्ट> शैली> लेआउट> पेंट> समग्र। (कम से कम क्रोम के लिए। अन्य ब्राउज़र समान हैं।)
jered

2
सिर्फ एक अनुमान: अलर्ट ब्लॉक होने से ब्राउज़र को एक रिपेंट स्टेप तक पहुंचने से रोकता है, इसलिए जबकि DOM बदल गया है, इसे अभी तक रीटेन करने की अनुमति नहीं दी गई है; फिर, बस एक अनुमान।
zzzzBov

2
@qbolec इस वीडियो की जाँच करें: youtu.be/r8caVE_a5KQ
apiblofbart

जवाबों:


131

इनर HTML सेट करना समकालिक है, जैसा कि सबसे अधिक परिवर्तन आप DOM के लिए कर सकते हैं। हालांकि, प्रतिपादन वेबपेज एक अलग कहानी है।

(याद रखें, DOM "डॉक्यूमेंट ऑब्जेक्ट मॉडल" के लिए खड़ा है। यह सिर्फ एक "मॉडल" है, डेटा का प्रतिनिधित्व करता है। उपयोगकर्ता अपनी स्क्रीन पर जो देखता है, वह उस मॉडल की एक तस्वीर है कि उसे कैसे दिखना चाहिए। इसलिए, मॉडल को तुरंत बदलना नहीं है तस्वीर बदलें - अपडेट होने में थोड़ा समय लगता है।)

जावास्क्रिप्ट चलाना और वेबपेज को रेंडर करना वास्तव में अलग से होता है। इसे सरलता से डालने के लिए, पहले पेज पर जावास्क्रिप्ट के सभी रन (इवेंट लूप से - अधिक विस्तार के लिए इस उत्कृष्ट वीडियो की जांच करें ) और फिर उसके बाद ब्राउज़र उपयोगकर्ता के देखने के लिए वेबपेज में किसी भी परिवर्तन का प्रतिपादन करता है। यही कारण है कि "ब्लॉकिंग" इतना बड़ा सौदा है - कम्प्यूटेशनल रूप से सघन कोड चलाने से ब्राउज़र को "रन जेएस" स्टेप और "रेंडर द पेज" चरण में जाने से रोकता है, जिससे पेज फ्रीज या हकलाने लगता है।

क्रोम की पाइपलाइन इस तरह दिखती है:

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

जैसा कि आप देख सकते हैं, सभी जावास्क्रिप्ट पहले होते हैं। तब पृष्ठ स्टाइल हो जाता है, बाहर रखा जाता है, चित्रित किया जाता है, और कंपोज़ किया जाता है - "रेंडर"। यह सभी पाइपलाइन हर फ्रेम को निष्पादित नहीं करेगी। यह इस बात पर निर्भर करता है कि कौन से पृष्ठ तत्व बदले गए, यदि कोई हो, और उन्हें फिर से कैसे प्रस्तुत करने की आवश्यकता है।

नोट: alert()जावास्क्रिप्ट स्टेप के दौरान भी सिंक्रोनस और निष्पादित होता है, यही कारण है कि वेबपेज में परिवर्तन देखने से पहले अलर्ट डायलॉग दिखाई देता है।

अब आप पूछ सकते हैं कि "होल्ड करें, वास्तव में पाइपलाइन में उस 'जावास्क्रिप्ट' चरण में क्या चलता है? क्या मेरा सभी कोड 60 बार प्रति सेकंड चलता है?" जवाब "नहीं" है, और यह जेएस ईवेंट लूप कैसे काम करता है, इस पर वापस जाता है। JS कोड केवल तभी चलता है जब वह स्टैक में होता है - इवेंट श्रोताओं, टाइमआउट, जैसी चीजों से। पिछला वीडियो देखें (वास्तव में)।

https://developers.google.com/web/fundamentals/performance/rendering/


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

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

27

हां, यह समकालिक है, क्योंकि यह काम करता है (आगे बढ़ो, इसे अपने कंसोल में टाइप करें):

document.body.innerHTML = 'text';
alert(document.body.innerHTML);// you will see a 'text' alert

पेज को बदलते हुए देखने से पहले आपको अलर्ट दिखाई देने का कारण यह है कि ब्राउज़र रेंडरिंग में अधिक समय लगता है और आपके जावास्क्रिप्ट को लाइन द्वारा निष्पादित करने में उतना तेज़ नहीं है।


धन्यवाद, मैंने जाँच की। लेकिन यह क्रोम के लिए कुछ विशिष्ट होना चाहिए - यह अन्य ब्राउज़रों में अपेक्षित रूप से काम करता है। या हो सकता है कि यह उनका दोष है कि वे जावास्क्रिप्ट की अगली पंक्ति में जाने के लिए पृष्ठ का इंतजार करते हैं?
अपाइफॉर्बार्ट

3
क्या अलर्ट सही पाठ दिखाता है? ( textमेरे उदाहरण में) यदि यह आपके समकालिक प्रश्न का उत्तर देगा। ब्राउज़र प्रतिपादन बनाम जावास्क्रिप्ट निष्पादन सेब और संतरे है:
d -_- b

यह करता है लेकिन सवाल के साथ कुछ नहीं करना है
एपिफेबोर्बार्ट

1
आप वास्तव में सवाल करते हैं "क्या इनर HTML अतुल्यकालिक है?"। यदि तुल्यकालिक होने के तुरंत बाद मूल्य का उपयोग किया जा सकता है, तो नहीं? मुझे लगता है कि आप पृष्ठ रेंडरिंग के बारे में अधिक पूछना चाहते हैं, न कि आंतरिक HTML की तुल्यकालिक गुणवत्ता।
d -_- b

8
हां, प्रश्न स्पष्ट रूप से गलत था, लेकिन मुझे नहीं पता था कि क्या पूछना है। अगर मुझे सही पता होता तो शायद जवाब मिल जाता। मैं मतलब होने का मतलब नहीं था, वैसे भी जवाब के लिए धन्यवाद!
अपाइफॉर्बार्ट

6

innerHTMLसंपत्ति वास्तविक तुल्यकालिक अपडेट कर दिया है, लेकिन दृश्य redraw है कि इस बदलाव का कारण बनता है एसिंक्रोनस रूप से होता है।

DOM को रेंडर करने वाला विज़ुअल क्रोम में अतुल्यकालिक है और यह तब तक नहीं होगा जब तक कि वर्तमान जावास्क्रिप्ट फंक्शन स्टैक क्लियर नहीं हो जाता है और ब्राउजर एक नए ईवेंट को स्वीकार करने के लिए स्वतंत्र है। अन्य ब्राउज़र जावास्क्रिप्ट कोड और ब्राउज़र रेंडरिंग को संभालने के लिए अलग थ्रेड्स का उपयोग कर सकते हैं, या वे कुछ घटनाओं को प्राथमिकता दे सकते हैं जबकि एक अलर्ट किसी अन्य घटना के निष्पादन को रोक रहा है।

आप इसे दो तरीकों से देख सकते हैं:

  1. यदि आप for(var i=0; i<1000000; i++) { }अपने अलर्ट से पहले जोड़ते हैं , तो आपने ब्राउज़र को रिड्राव करने के लिए बहुत समय दिया है, लेकिन ऐसा नहीं है, क्योंकि फ़ंक्शन स्टैक साफ़ नहीं हुआ है ( addअभी भी चल रहा है)।

  2. यदि आप alertएक एसिंक्रोनस के माध्यम से अपनी देरी करते हैं setTimeout(function() { alert('random'); }, 1), तो redraw प्रक्रिया को सेटटाइमआउट में देरी से फ़ंक्शन के आगे जाना होगा।

    • यदि आप समय-समय पर उपयोग करते हैं तो यह काम नहीं करता है 0, संभवतः क्योंकि Chrome 0किसी अन्य ईवेंट (या कम से कम रिड्रा इवेंट्स) से पहले टाइमआउट को प्राथमिकता देता है ।

जवाब देने के लिए शुक्रिया! ऐसा नहीं है कि यहां तक कि कृपया setTimeout(func, 1): हर बार काम नहीं किया, इस वीडियो को देखने के youtu.be/r8caVE_a5KQ
apieceofbart
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.