Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> JavaScript

जावास्क्रिप्ट के साथ एक प्रदर्शनकारी "व्यूपोर्ट आयाम प्राप्त करें" मिनी-ऐप बनाएं

एक शुरुआती-अनुकूल और व्यावहारिक वैनिला जावास्क्रिप्ट ट्यूटोरियल। मुख्य निष्कर्ष: कैसे हाई-परफॉरमेंस विंडो इवेंट लिखें जो हमारे उपयोगकर्ताओं के हार्डवेयर को न मारें।

लक्ष्य: पूर्ण शुरुआती से मध्यवर्ती

आज हम "व्यूपोर्ट आयाम" नामक एक शानदार छोटा ऐप बना रहे हैं। यह सुविधा एक चीज़ वास्तव में अच्छी तरह से करती है: जब आप अपने ब्राउज़र विंडो का आकार बदलते हैं तो यह आपके ब्राउज़र व्यूपोर्ट की चौड़ाई और ऊंचाई के मान प्रदर्शित करता है।

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

व्यूपोर्ट आयाम

जावास्क्रिप्ट के साथ एक प्रदर्शनकारी  व्यूपोर्ट आयाम प्राप्त करें  मिनी-ऐप बनाएं

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

तकनीकी विषय:

  • createElement() मेथड से एलिमेंट कैसे बनाएं।
  • Style ऑब्जेक्ट से एलिमेंट को स्टाइल कैसे करें।
  • विंडो ऑब्जेक्ट के resize इवेंट को कैसे सेटअप और उपयोग करें।
  • innerWidth और innerHeight प्रॉपर्टी से अपने ब्राउज़र व्यूपोर्ट की चौड़ाई और ऊंचाई कैसे प्राप्त करें।
  • फंक्शन के बाहर फंक्शन कैसे कॉल करें (कॉलबैक)।
  • शर्तीय (सही/गलत) if स्टेटमेंट कैसे काम करते हैं।
  • setTimeout() का उपयोग करके टाइमर के साथ कोड निष्पादन में देरी कैसे करें।
  • clearTimeout() से टाइमर कैसे रीसेट करें।
  • इवेंट थ्रॉटलर फंक्शन का उपयोग करके विंडो इवेंट के प्रदर्शन में नाटकीय रूप से सुधार कैसे करें।
  • MS और FPS (मिलीसेकंड और फ्रेम प्रति सेकंड) के बीच संबंध।
  • अनुभवजन्य प्रदर्शन और हार्डवेयर प्रदर्शन के बीच महत्वपूर्ण अंतर।

दृष्टिकोण

हम अपने व्यूपोर्ट आयाम ऐप के दो संस्करण बना रहे हैं।

  • संस्करण 1 ऐप को काम करने के बारे में है। यह मसौदा है, लेकिन अंतिम उत्पाद नहीं।
  • संस्करण 2 संस्करण 1 में सुधार के बारे में है। हम सीखेंगे कि अपने कोड को अधिक प्रदर्शनकारी, ऊर्जा-कुशल, और पढ़ने में आसान कैसे बनाएं।

चीजों को जावास्क्रिप्ट-केंद्रित रखने के लिए, हम सब कुछ जावास्क्रिप्ट कोड में करेंगे। सब कुछ एक जावास्क्रिप्ट फ़ाइल में रखकर, हमारा ऐप आपके किसी भी मौजूदा प्रोजेक्ट में जोड़ना आसान होगा।

क्या आप पूर्ण शुरुआती हैं? तो मैं सुझाव देता हूं कि आप CodePen का उपयोग करके साथ चलें। आपको इसका उपयोग करने के लिए साइन अप करने की भी आवश्यकता नहीं है। मैंने एक काफी लोकप्रिय CodePen वीडियो ट्यूटोरियल प्रकाशित किया है जिसे आप यहां देख सकते हैं।

कैसे सीखें

यदि आप भ्रमित हैं, तो कुछ पैराग्राफ पीछे जाएं और सुनिश्चित करें कि आपने कुछ महत्वपूर्ण नहीं छोड़ा है। आप समस्याओं को पहले स्वयं हल करने की कोशिश करके और फिर दूसरे संदर्भ कोड देखकर अधिक सीखेंगे।

यदि आप खो जाते हैं तो आप हमेशा तैयार कोड का संदर्भ ले सकते हैं:

  • संस्करण 1
  • संस्करण 2

शुरू करते हैं!

व्यूपोर्ट आयाम [संस्करण 1.0]

कोडिंग शुरू करने से पहले, आइए प्रोजेक्ट आवश्यकताओं पर एक नज़र डालते हैं।

आवश्यकताएं

  • विंडो चौड़ाई और ऊंचाई प्रदर्शित करने के लिए एक कंटेनर होना चाहिए।
  • यह हमारी विंडो के ऊपरी दाएं कोने पर स्थित होना चाहिए।
  • यह डिफ़ॉल्ट रूप से छिपा होना चाहिए।
  • जैसे ही विंडो का आकार बदला जाता है, यह दिखना चाहिए।
  • नवीनतम विंडो रिसाइज के 3 सेकंड बाद यह छिप जाना चाहिए।

यह संस्करण 1 के लिए सुविधा आवश्यकताओं का सार है।

आइए कोडिंग शुरू करें!

डिस्प्ले कंटेनर बनाना और स्टाइल करना

सबसे पहले, आइए createElement मेथड का उपयोग करके हमारे व्यूपोर्ट आयाम ऐप के लिए एक div एलिमेंट बनाएं और इसे एक वेरिएबल को असाइन करें:

var viewportDimensions = document.createElement("div");

अब हमारे पास एक वेरिएबल के अंदर संग्रहीत एक खाली <div></div> एलिमेंट है।

ब्राउज़र में, सभी HTML एलिमेंट एलिमेंट ऑब्जेक्ट द्वारा दर्शाए जाते हैं। इन एलिमेंट ऑब्जेक्ट में गुण और मेथड होते हैं जिन्हें हम जावास्क्रिप्ट से एक्सेस कर सकते हैं।

हम चाहते हैं कि हमारी व्यूपोर्ट चौड़ाई और ऊंचाई हमारे ब्राउज़र विंडो के ऊपरी दाएं कोने पर प्रदर्शित हो। आइए इसका ध्यान रखें और HTML DOM Style ऑब्जेक्ट गुणों तक पहुंचकर हमारे div एलिमेंट को कुछ स्टाइलिंग दें:

viewportDimensions.style.position = "fixed";
viewportDimensions.style.right = "0";
viewportDimensions.style.top = "0";
viewportDimensions.style.padding = "16px";
viewportDimensions.style.zIndex = "3";
viewportDimensions.style.fontSize = "22px";

ऊपर का सिंटैक्स डॉट नोटेशन है। सरल शब्दों में, इसका मतलब है कि हम किसी ऑब्जेक्ट के गुणों या मेथड तक पहुंचने के लिए . का उपयोग करते हैं। इसलिए ऊपर के उदाहरण में, हम कह रहे हैं:

  • हे viewportDimensions
  • मुझे Style ऑब्जेक्ट तक पहुंच दें
  • ताकि मैं इसके स्टाइलिंग गुण तक पहुंच सकूं

Style ऑब्जेक्ट के साथ स्टाइलिंग CSS के साथ स्टाइलिंग जैसा है। लेकिन Style ऑब्जेक्ट इनलाइन स्टाइल का उपयोग करता है। स्टाइलिंग गुण सीधे HTML एलिमेंट में जुड़ जाते हैं, बाहरी CSS स्टाइलशीट में नहीं।

आइए पुष्टि करें कि हमारा कोड काम करता है, हमारे व्यूपोर्ट आयाम <div> एलिमेंट को हमारे HTML दस्तावेज़ के <body> एलिमेंट में जोड़कर।

सबसे पहले, आइए अपने दस्तावेज़ के बॉडी एलिमेंट का संदर्भ संग्रहीत करने के लिए एक वेरिएबल घोषित करें। अपने जावास्क्रिप्ट फ़ाइल के शीर्ष पर निम्न कोड जोड़ें।

var body = document.querySelector("body");

अब आइए अपने व्यूपोर्ट आयाम के div एलिमेंट को बॉडी एलिमेंट के अंदर जोड़ें। अपने जावास्क्रिप्ट फ़ाइल के नीचे (अंतिम स्टाइल के नीचे) निम्न कोड डालें:

body.appendChild(viewportDimensions);

appendChild() एक मेथड है जो एक नोड को दूसरे नोड के अंदर जोड़ता (ऐड करता है)। DOM में सब कुछ एक नोड है, और नोड्स के विभिन्न प्रकार हैं। इस मामले में, हम एक div एलिमेंट नोड को बॉडी एलिमेंट नोड के अंदर जोड़ रहे हैं।

चूंकि हमारे div एलिमेंट में अभी तक कोई सामग्री नहीं है, हम यह पता लगाने के लिए एलिमेंट में एक अस्थायी बॉर्डर जोड़ सकते हैं कि हमारा वर्तमान कोड काम करता है या नहीं:

viewportDimensions.style.border = "10px solid";

यदि यह काम करता है तो आपको अब अपनी विंडो के ऊपरी दाएं कोने में एक मोटी काली बॉर्डर वाला एक छोटा बॉक्स दिखाई देना चाहिए:

जावास्क्रिप्ट के साथ एक प्रदर्शनकारी  व्यूपोर्ट आयाम प्राप्त करें  मिनी-ऐप बनाएं

आप अपने ब्राउज़र विंडो में राइट-क्लिक करके भी जांच सकते हैं। फिर अपने ब्राउज़र DevTools तक पहुंचने के लिए इंस्पेक्ट पर क्लिक करें।

अब एलिमेंट्स टैब के तहत, अपने body एलिमेंट का पता लगाएं, और आपको कुछ इनलाइन स्टाइल गुणों के साथ एक खाली div एलिमेंट दिखाई देना चाहिए।

जावास्क्रिप्ट के साथ एक प्रदर्शनकारी  व्यूपोर्ट आयाम प्राप्त करें  मिनी-ऐप बनाएं ध्यान दें कि जब आप DevTools में इस पर माउस घुमाते हैं तो अदृश्य div ऊपरी दाएं कोने में हाइलाइट हो जाता है।

यहां अब तक के हमारे सभी कोड का अवलोकन है:

// बॉडी एलिमेंट चुनें
var body = document.querySelector("body");
// div एलिमेंट बनाएं
var viewportDimensions = document.createElement("div");
// एलिमेंट स्टाइल करें
viewportDimensions.style.position = "fixed";
viewportDimensions.style.right = "0";
viewportDimensions.style.top = "0";
viewportDimensions.style.padding = "16px";
viewportDimensions.style.zIndex = "3";
viewportDimensions.style.fontSize = "22px";
// div एलिमेंट को बॉडी एलिमेंट के अंदर जोड़ें
body.appendChild(viewportDimensions);

बहुत बढ़िया, हमारे div एलिमेंट को बनाया गया है, स्टाइल किया गया है, और हमारे बॉडी एलिमेंट के अंदर जोड़ा गया है। अगला है विंडो रिसाइज इवेंट।

विंडो रिसाइज इवेंट सेटअप करना

विंडो ऑब्जेक्ट आपके ब्राउज़र विंडो को दर्शाता है। इसमें कई मेथड हैं, जिनमें addEventListener शामिल है। यह मेथड कई प्रकार के विंडो इवेंट को सुन सकता है, जैसे स्क्रॉलिंग, क्लिकिंग, टाइपिंग, और रिसाइजिंग।

हम 'resize' इवेंट का उपयोग करने जा रहे हैं। body.appendChild के नीचे निम्न जोड़ें:

window.addEventListener("resize", function() {
  // विंडो रिसाइज होने पर निष्पादित करने के लिए कोड
});

नोट: टिप्पणियां // ब्राउज़र द्वारा व्याख्या नहीं की जातीं, वे केवल हमारे मनुष्यों के लिए हैं

पहले हमने div एलिमेंट के गुणों को हथियाने के लिए डॉट नोटेशन का उपयोग किया था। अब हम इसका उपयोग विंडो ऑब्जेक्ट पर एक मेथड तक पहुंचने के लिए करते हैं: addEventListener।

हम इवेंट लिस्टनर को दो आर्गुमेंट पास कर रहे हैं: 'resize' और function()। हमने पहले ही रिसाइज इवेंट पर चर्चा की है, लेकिन फंक्शन किस लिए है?

function() उस कोड ब्लॉक को सेट करता है जिसे हम हर बार विंडो रिसाइज इवेंट सक्रिय होने पर निष्पादित करना चाहते हैं (जैसे ही आप अपनी विंडो का आकार बदलते हैं)। कोड ब्लॉक वह है जो घुंघराले ब्रेसिज़ { } के अंदर है (जिसे फंक्शन बॉडी भी कहा जाता है) जिसमें अब तक केवल एक // टिप्पणी है।

हर बार जब हम विंडो इवेंट को कॉल करते हैं, तो यह function() को घुंघराले ब्रेसिज़ { } के अंदर का कोड चलाने के लिए कहता है।

यह पुष्टि करने के लिए कि यह काम कर रहा है, आइए console.log() का उपयोग करके इसका परीक्षण करें:

window.addEventListener("resize", function() {
  // विंडो रिसाइज होने पर निष्पादित करने के लिए कोड
  console.log("काम कर रहा है!");
});

अब अपनी विंडो का आकार बदलें। यदि आपका कंसोल कई बार 'काम कर रहा है!' प्रिंट करता है, तो इसका मतलब है कि आपका विंडो रिसाइज इवेंट काम कर रहा है।

कंसोल तक पहुंचना

CodePen में कंसोल तक पहुंचने के लिए, अपनी विंडो के निचले बाएं कोने में कंसोल बटन पर क्लिक करें। क्रोम में कंसोल तक पहुंचने के लिए, यहां कीबोर्ड शॉर्टकट हैं:

  • Cmd + Opt + J (Mac)।
  • Ctrl + Shift + J (विंडोज / लिनक्स)

ठीक है, आइए अपने विंडो इवेंट को काम पर लगाएं!

ब्राउज़र चौड़ाई और ऊंचाई को पिक्सेल में लौटाना

अगला कदम व्यूपोर्ट चौड़ाई और ऊंचाई के संख्यात्मक मान प्राप्त करना है। हम चाहते हैं कि मान तुरंत अपडेट हों, जैसे ही हम अपनी विंडो का आकार बदलते हैं। विंडो ऑब्जेक्ट आपके ब्राउज़र विंडो को दर्शाता है। इसमें innerWidth और innerHeight नामक कुछ शानदार गुण हैं।

अंदाजा लगाइए वे क्या करते हैं?

हाँ, वे आपके ब्राउज़र विंडो की चौड़ाई और ऊंचाई को पिक्सेल में लौटाते हैं (स्क्रॉलबार सहित)। आइए इसकी पुष्टि करें, और उन चौड़ाई और ऊंचाई संपत्ति मानों को लौटाने के लिए console.log() का उपयोग करें।

चूंकि हम इसे डायनामिक रूप से वर्तमान मान प्राप्त करना चाहते हैं, हमें अपने console.log() को रिसाइज इवेंट के फंक्शन ब्लॉक के अंदर रखना होगा:

window.addEventListener("resize", function() {
  // विंडो रिसाइज होने पर निष्पादित करने के लिए कोड
  console.log("चौड़ाई:", window.innerWidth);
  console.log("ऊंचाई:", window.innerHeight);
});

console.log() में 'चौड़ाई:' और 'ऊंचाई:' टेक्स्ट केवल कंसोल आउटपुट को स्पष्ट करने के लिए हैं।

हमें वास्तव में चौड़ाई और ऊंचाई मान प्राप्त करने के लिए window. लिखने की आवश्यकता नहीं है, केवल innerWidth और innerHeight काम करेंगे। मैं भ्रम से बचने के लिए ऐसा करता हूं।

यदि यह काम करता है तो आपका कंसोल अब आपके वर्तमान व्यूपोर्ट के आयामों को लगातार प्रिंट करेगा जब तक आप अपने ब्राउज़र विंडो का आकार बदलते हैं।

यह ऐसा दिखना चाहिए:

जावास्क्रिप्ट के साथ एक प्रदर्शनकारी  व्यूपोर्ट आयाम प्राप्त करें  मिनी-ऐप बनाएं

अब हम कहीं पहुंच रहे हैं!

आइए console.log() से छुटकारा पाएं और इसके बजाय चौड़ाई और ऊंचाई गुणों को उनके अपने वेरिएबल में असाइन करें ताकि हम उनके संदर्भ को संग्रहीत कर सकें:

window.addEventListener("resize", function() {
  // विंडो रिसाइज होने पर निष्पादित करने के लिए कोड
  var width = window.innerWidth;
  var height = window.innerHeight;
});

अब width और height में हमेशा विंडो चौड़ाई और ऊंचाई संपत्ति के वर्तमान मान होंगे। आपको लौटाए गए मानों को हमेशा एक वेरिएबल में असाइन करने की आवश्यकता नहीं है, लेकिन यह एक अच्छा अभ्यास है क्योंकि यह आपको बाद में उस जानकारी का उपयोग या बदलाव करने की अनुमति देता है।

यह पुष्टि करने के लिए कि आपके नए वेरिएबल काम कर रहे हैं, उन्हें कंसोल पर प्रिंट करने का प्रयास करें:

window.addEventListener("resize", function() {
  // विंडो रिसाइज होने पर निष्पादित करने के लिए कोड
  var width = window.innerWidth;
  var height = window.innerHeight;
  console.log(width);
  console.log(height);
});

यदि सब कुछ काम करता है, तो आप अपने console.log को हटा सकते हैं, और आगे बढ़ सकते हैं।

चौड़ाई और ऊंचाई मानों को div एलिमेंट में जोड़ना

हम लौटाए गए चौड़ाई और ऊंचाई मानों को अपने div एलिमेंट में जोड़ना चाहते हैं। अधिक विशेष रूप से हम मानों को अंदर अपने div एलिमेंट के शुरुआती और समापन टैग में एम्बेड करना चाहते हैं:

&lt;div&gt; हम यहां चौड़ाई और ऊंचाई मान चाहते हैं &lt;/div&gt;

ऐसा करने के लिए हमें उस वेरिएबल को पकड़ने की आवश्यकता है जो हमारे div एलिमेंट को संग्रहीत करता है: viewportDimensions। फिर हमें अपने एलिमेंट ऑब्जेक्ट पर एक गुण तक पहुंचने की आवश्यकता है, जिसे textContent कहा जाता है। हम पहले से उसी डॉट नोटेशन का उपयोग करते हैं:

viewportDimensions.textContent;

अब हमें बस अपने चौड़ाई और ऊंचाई वेरिएबल को असाइन करना होगा:

viewportDimensions.textContent = width + "px" + " x " + height + "px";

अब अपने ब्राउज़र विंडो का आकार बदलने का प्रयास करें। यदि आपने सब कुछ सही किया तो यह अब आपके विंडो के ऊपरी दाएं कोने पर वर्तमान चौड़ाई और ऊंचाई मान प्रदर्शित करना चाहिए।

जावास्क्रिप्ट के साथ एक प्रदर्शनकारी  व्यूपोर्ट आयाम प्राप्त करें  मिनी-ऐप बनाएं

मुझे पता है कि ऊपर उपयोग किया गया कोड सिंटैक्स थोड़ा भ्रमित करने वाला लग सकता है।

आइए इसे तोड़ दें:

textContent एलिमेंट ऑब्जेक्ट का एक गुण है। दस्तावेज़ में किसी भी एलिमेंट में यह होता है, जिसमें हमारे व्यूपोर्ट आयाम div एलिमेंट भी शामिल हैं।

textContent एक नोड लौटाता है, विशेष रूप से एक टेक्स्ट नोड। उदाहरण के लिए: एक पैराग्राफ एलिमेंट के अंदर का टेक्स्ट: <p>कुछ टेक्स्ट...</p>, एक टेक्स्ट नोड है।

हमारा viewportDimensions वेरिएबल एक खाली <div> एलिमेंट रखता था। अब यह शुरुआती और समापन div एलिमेंट टैग के बीच संख्यात्मक पिक्सेल मानों के साथ एक टेक्स्ट नोड लौटाता है:

width + "px" + " x " + height + "px";

width और height दोनों में एक पिक्सेल नंबर मान होता है। हम केवल 'px' और ' x ' (स्ट्रिंग्स) जोड़ते हैं ताकि चौड़ाई और ऊंचाई वेरिएबल को अलग किया जा सके, और सभी को यह स्पष्ट हो सके कि हम जो मान लौटाते हैं वे पिक्सेल में हैं।

setTimeout() के साथ काउंटडाउन टाइमर जोड़ना

हम नहीं चाहते कि जब हम अपनी विंडो का आकार नहीं बदल रहे हों तो चौड़ाई और ऊंचाई लगातार प्रदर्शित हो। आइए व्यूपोर्ट आयाम के div एलिमेंट को ठीक तीन सेकंड बाद गायब कर दें जब हम अपने ब्राउज़र विंडो का आकार बदलना बंद कर दें।

ऐसा करने के लिए हमें विंडो ऑब्जेक्ट के एक और मेथड का उपयोग करने की आवश्यकता है, जिसे setTimeout कहा जाता है। यह मेथड एक निर्दिष्ट संख्या में मिलीसेकंड के बाद एक function() को एक बार निष्पादित करने के लिए डिज़ाइन किया गया है।

यह ऐसे काम करता है:

setTimeout(functionToExecute, 3000);

1000 ms = 1 सेकंड। तो ऊपर 3000 का मतलब 3 सेकंड है।

हम कौन सा फंक्शन निष्पादित करना चाहते हैं? वह जो हमारे व्यूपोर्ट आयाम के div एलिमेंट को हटा देता है।

हमारे पास अभी तक ऐसा कोई फंक्शन नहीं है, आइए एक बनाएं और इसे removeViewportDimensions() कहें और इसके कोड ब्लॉक { } के अंदर इसे हमारे div एलिमेंट को हटाने के लिए कहें।

निम्न कोड को अपने विंडो इवेंट फंक्शन के ऊपर जोड़ें:

function removeViewportDimensions() {
  viewportDimensions.style.display = "none";
}

display गुण निर्दिष्ट करता है कि कोई एलिमेंट कैसे या क्या प्रदर्शित होता है। इसे 'none' पर सेट करके, हम इसे छिपा रहे हैं।

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

setTimeout(removeViewportDimensions, 3000);

अब हर बार विंडो रिसाइज इवेंट सक्रिय होता है, setTimeout 3 सेकंड की उलटी गिनती सेट करता है। दूसरे शब्दों में: हम removeViewportDimensions() फंक्शन को 3 सेकंड के लिए देरी करते हैं।

जब 3 सेकंड पूरे हो जाते हैं, तो removeViewportDimensions() फंक्शन कॉल किया जाता है, और इसका कोड निष्पादित होता है:

जावास्क्रिप्ट के साथ एक प्रदर्शनकारी  व्यूपोर्ट आयाम प्राप्त करें  मिनी-ऐप बनाएं

अब हमारे div एलिमेंट का display गुण 'none' पर सेट है, और यह छिपा हुआ है।

लेकिन हमारे पास एक समस्या है

यदि आप div एलिमेंट हटाए जाने के ठीक बाद दूसरी बार अपने ब्राउज़र विंडो का आकार बदलने का प्रयास करते हैं, तो div एलिमेंट फिर से दिखाई नहीं देगा। ऐसा इसलिए है क्योंकि हमारे प्रोग्राम में होने वाली अंतिम चीज़ यह है कि हमारे div एलिमेंट का display गुण 'none' पर सेट हो जाता है।

हमारे प्रोग्राम में कहीं भी ऐसा नहीं कहा गया है कि हम चाहते हैं कि हमारा div एलिमेंट फिर से दृश्यमान हो।

लेकिन फिर यह पहली बार दृश्यमान क्यों था? क्योंकि डिफ़ॉल्ट रूप से एक <div> एलिमेंट एक तथाकथित ब्लॉक-लेवल एलिमेंट है। इसका मतलब है कि इसका डिफ़ॉल्ट display गुण मान 'block' है — जो एक दृश्यमान डिस्प्ले प्रकार है।

हम अपने div एलिमेंट के साथ जो आखिरी चीज़ करते हैं वह इसके display मान को 'none' पर सेट करना है। तो वह मान अभी भी एलिमेंट पर होगा जब हम दूसरी बार रिसाइज इवेंट चलाते हैं। जब तक आप अपना पेज रीफ्रेश नहीं करते।

यह ठीक करना आसान है। अपने विंडो रिसाइज इवेंट के कोड ब्लॉक के अंदर निम्न जोड़ें (setTimeout के ऊपर!):

viewportDimensions.style.display = "block";

अब हर बार रिसाइज इवेंट चलने पर हमारे div एलिमेंट का display गुण 'block' पर सेट हो जाता है। अपनी विंडो का आकार बदलें, div एलिमेंट के छिपने की प्रतीक्षा करें, और फिर से आकार बदलें।

जावास्क्रिप्ट के साथ एक प्रदर्शनकारी  व्यूपोर्ट आयाम प्राप्त करें  मिनी-ऐप बनाएं

बहुत बढ़िया, हमारा ऐप काम करता है!

खैर... लगभग। हमारे पास एक और समस्या है। यदि आप अपने ब्राउज़र विंडो का आकार विस्तारित अवधि (3 सेकंड से अधिक) के लिए बदलने का प्रयास करते हैं तो div एलिमेंट झिलमिलाने लगेगा। ऐसा लगेगा जैसे यह एक लाइट थी जो लगातार चालू और बंद हो रही हो।

जावास्क्रिप्ट के साथ एक प्रदर्शनकारी  व्यूपोर्ट आयाम प्राप्त करें  मिनी-ऐप बनाएं यह हमारे ऐप के योग्य नहीं है!

ऐसा होता है, क्योंकि हम अपने काउंटडाउन टाइमर को रीसेट नहीं कर रहे हैं। हर बार जब हम अपना व्यूपोर्ट रिसाइज करते हैं, तो विंडो इवेंट अपने फंक्शन कोड ब्लॉक को उतनी बार निष्पादित करता है जितना वह कर सकता है। तो हमारा removeViewportDimensions() फंक्शन भी कई बार कॉल किया जाता है।

यह हमारे ऐप में ओवरलैपिंग कोड निष्पादन का एक गुच्छा पैदा करता है। हमारे div एलिमेंट को display = 'none' गुण और display = 'block' गुण एक ही समय में हथौड़े की तरह मारा जा रहा है।

यह हमारे div एलिमेंट को लगातार दिखाता और छिपाता है, और झिलमिलाहट का कारण बनता है। यह बेकार है। इस समस्या को हल करने के लिए, हमें यह सीखना होगा कि जावास्क्रिप्ट में टाइमर क्लियर करना कैसे काम करता है।

काउंटडाउन टाइमर रीसेट करना

हम clearTimeout() मेथड का उपयोग करके मौजूदा टाइमर को क्लियर कर सकते हैं। यह मेथड setTimeout मेथड के साथ सेट किए गए टाइमर को क्लियर करने के लिए डिज़ाइन किया गया है। वे पार्टनर मेथड की तरह हैं।

मौजूदा टाइमर को क्लियर करना वही है जो हम चाहते हैं। हम केवल setTimeout() टाइमर को एक बार प्रति रिसाइज इवेंट चलाना चाहते हैं।

आप सोच सकते हैं कि हम setTimeout() पर clearTimeout() ऐसे चला सकते हैं:

clearTimeout(setTimeout);

लेकिन यह काम नहीं करेगा। clearTimeout() मेथड का उपयोग करने के लिए, आपको setTimeout मेथड बनाते समय एक ग्लोबल वेरिएबल का उपयोग करना होगा।

जावास्क्रिप्ट में दो स्कोप हैं: ग्लोबल और लोकल:

  • एक ग्लोबल वेरिएबल एक वेरिएबल है जिसे फंक्शन के बाहर घोषित किया गया है (ग्लोबल स्कोप में)।
  • एक लोकल वेरिएबल एक वेरिएबल है जिसे फंक्शन के अंदर घोषित किया गया है (लोकल स्कोप में)।

इसका मतलब है कि यदि हम setTimeout() को क्लियर करना चाहते हैं तो हमें पहले इसे एक ग्लोबल वेरिएबल में असाइन करना होगा, और फिर हम उस वेरिएबल पर clearTimeout() कॉल करके इसे रीसेट कर सकते हैं।

आइए अपना ग्लोबल वेरिएबल बनाएं, और इसे resizeTimeout कहें:

var resizeTimeout;

इस वेरिएबल को अपनी जावास्क्रिप्ट फ़ाइल के सबसे ऊपर रखें।

अभी यह सिर्फ एक खाली वेरिएबल है। यह केवल पहली बार हमारे रिसाइज इवेंट शुरू होने तक खाली रहेगा।

यदि आप console.log(resizeTimeout) का उपयोग करने का प्रयास करते हैं तो आपको अपरिभाषित लौटाया जाएगा। अपरिभाषित एक गलत मान प्रकार है, जो महत्वपूर्ण है। आप जल्द ही समझ जाएंगे क्यों।

अब, पहले के अपने setTimeout() फंक्शन को लें और इसे resizeTimeout वेरिएबल में असाइन करें:

resizeTimeout = setTimeout(removeViewportDimensions, 3000);

अब ग्लोबल resizeTimeout वेरिएबल को हमारे setTimeout फंक्शन के बारे में जानकारी प्राप्त होगी, जैसे ही रिसाइज इवेंट सक्रिय होता है।

अब हम हर बार अपने विंडो रिसाइज इवेंट चलने पर setTimeout() का उपयोग कर सकते हैं। ग्लोबल resizeTimeout वेरिएबल पर clearTimeout() सेट करें। ऐसे:

clearTimeout(resizeTimeout);

कोड को अपने resizeTimeout = setTimeout() के ठीक ऊपर रखें ताकि यह ऐसा दिखे:

clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(removeViewportDimensions, 3000);

ठीक है, अब अपने रिसाइज इवेंट को 5-6 सेकंड के लिए चलाएं, और आप देखेंगे कि झिलमिलाहट चली गई है!

भ्रमित? आइए बात करते हैं कि कोड में क्या होता है।

जावास्क्रिप्ट इंटरप्रेटर (एक इंजन जो आपके ब्राउज़र में चलता है) आपका कोड पढ़ेगा और:

  • इसे लाइन दर लाइन निष्पादित करेगा
  • एक समय में एक लाइन
  • ऊपर से नीचे तक

हमारा कोड ऊपर से नीचे तक निष्पादित होता रहेगा, जब तक हम अपनी विंडो का आकार बदलते रहेंगे। रिसाइजिंग की हर छोटी मात्रा एक नया विंडो इवेंट फायर करेगी। तो जावास्क्रिप्ट इंटरप्रेटर हमारे कोड को प्रति सेकंड कई बार पढ़ता और निष्पादित करता है।

हर बार हमारे विंडो इवेंट का फंक्शन अपना कोड ब्लॉक निष्पादित करता है, clearTimeout() resizeTimeout वेरिएबल पर कतार में किसी भी मौजूदा उलटी गिनती को रीसेट कर देगा।

अंतिम कोड लाइन पर, हम setTimeout() असाइन करते हैं।

तो आखिरी चीज़ जो होगी वह हमेशा एक 3 सेकंड की उलटी गिनती होगी जो resizeTimeout को असाइन की जाती है। उससे पहले शुरू की गई कोई भी उलटी गिनती clearTimeout() द्वारा मिटा दी जाएगी।

बहुत बढ़िया! संस्करण 1 पूरा हुआ। आप यहां पूरा कोड देख सकते हैं। आइए संस्करण 2 पर चलते हैं, जहां हम विशेष रूप से प्रदर्शन पर ध्यान केंद्रित करने जा रहे हैं।


व्यूपोर्ट आयाम [संस्करण 2]

हमारा ऐप काम करता है, लेकिन क्या यह काफी अच्छा है? उस प्रश्न का उत्तर देने के लिए हमें दो महत्वपूर्ण बातों पर विचार करने की आवश्यकता है:

  • अनुभवजन्य प्रदर्शन: उपयोगकर्ता अनुभव (UX)।
  • हार्डवेयर प्रदर्शन (उपयोग और दक्षता)।

UX के दृष्टिकोण से, मुझे लगता है कि हमारा ऐप बहुत अच्छा प्रदर्शन करता है। इसका प्रतिक्रिया समय बेहद तेज़ है, और यह पुरानी स्क्रीन पर भी बहुत अच्छी तरह से रेंडर होता है (मैंने कुछ दशक पुराने दिग्गजों पर टेस्ट किया)। हम हमेशा विजुअल्स (UI डिज़ाइन) को ऑप्टिमाइज़ करने के बारे में बहस कर सकते हैं। लेकिन शुद्ध कार्यक्षमता के आधार पर, हमारा ऐप अच्छा काम करता है।

लेकिन हार्डवेयर प्रदर्शन के दृष्टिकोण से, हमारा ऐप वास्तव में खराब है। हमारा ऐप CPU और GPU संसाधनों का एक टन उपयोग कर रहा है, इसकी तुलना में इसकी तकनीकी आवश्यकताएं कितनी मामूली हैं।

क्या आप पता लगा सकते हैं क्यों? यह कुछ ऐसा नहीं है जिसके बारे में आप सहज रूप से सोचते हैं जब आप विंडो इवेंट के लालची स्वभाव से परिचित नहीं होते।

यहां समस्या है:

हर बार जब हम अपनी ब्राउज़र विंडो का आकार बदलते हैं, तो हमारे ऐप का विंडो इवेंट इसके फंक्शन को सैकड़ों बार निष्पादित कर रहा है। बस कुछ सेकंड में!

मैंने CodePen पर एक फंक्शन डाला जो समस्या को विज़ुअलाइज़ करता है। ध्यान दें कि प्रति सेकंड कितने फंक्शन निष्पादित होते हैं। कुल काउंट को तेजी से छत के माध्यम से उड़ते हुए भी देखें:

CodePen उदाहरण

यह भयानक और पूरी तरह से अनावश्यक है! हमारा कोड जितना चाहिए उससे कहीं अधिक संसाधनों का उपयोग कर रहा है।

यह देखने के लिए कि ब्राउज़र इवेंट के दौरान आपका CPU और GPU कितना काम कर रहे हैं, आप क्रोम के टास्क मैनेजर को लॉन्च कर सकते हैं:

जावास्क्रिप्ट के साथ एक प्रदर्शनकारी  व्यूपोर्ट आयाम प्राप्त करें  मिनी-ऐप बनाएं

अपने ब्राउज़र विंडो का आकार बदलने का प्रयास करें। टास्क मैनेजर के अंदर, आपको अपने सक्रिय ब्राउज़र टैब के बगल में CPU और GPU % उपयोग मिलेगा।

पूर्ण बनाम सापेक्ष हार्डवेयर उपयोग

पूर्ण और सापेक्ष हार्डवेयर उपयोग के बीच अंतर करना महत्वपूर्ण है। पूर्ण (कुल) हार्डवेयर उपयोग के दृष्टिकोण से, हमारा छोटा ऐप अधिक नुकसान नहीं करेगा। अधिकांश कंप्यूटर इससे हिलने के लिए बहुत शक्तिशाली हैं।

लेकिन सापेक्ष उपयोग के दृष्टिकोण से, हमारा ऐप भयानक रूप से अक्षम है। और यही समस्या है। हम कभी भी प्रदर्शन की उपेक्षा करने की आदत में नहीं पड़ना चाहते, क्योंकि यह हमें परेशान करेगा, और वापस आकर हमें काटेगा।

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

विंडो इवेंट कैसे निष्पादित होता है

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

प्रति सेकंड फंक्शन कितनी बार निष्पादित होते हैं?

यह हर 4 से हर 40 मिलीसेकंड तक कुछ भी हो सकता है। यह बहुत सारे कारकों पर निर्भर करता है, जिनमें शामिल हैं:

  • आपका CPU और GPU (हार्डवेयर) कितना शक्तिशाली है?
  • आप किस ब्राउज़र का उपयोग कर रहे हैं?
  • आप जो सॉफ़्टवेयर (कोड) चला रहे हैं वह कितना जटिल है? क्या इसमें एनिमेशन शामिल हैं?
  • आपका हार्डवेयर इस समय और क्या कर रहा है? क्या दूसरे टैब में YouTube वीडियो चल रहा है?

आपका हार्डवेयर दिए गए समय पर जो भी संसाधन उपलब्ध हैं, उनका उपयोग करता है जब आप इसे कुछ करने के लिए कहते हैं।

कभी-कभी इसके पास तुरंत आपके अनुरोध का जवाब देने के लिए पर्याप्त मुफ्त संसाधन नहीं होंगे क्योंकि एक ही समय में बहुत सारे ऐप चल रहे हैं।

यह धीमी प्रतिक्रिया समय, स्क्रीन ग्लिच, फ्रीजिंग, और अन्य मुद्दों का कारण बन सकता है।

हार्डवेयर उपयोग जुड़ जाता है। यही कारण है कि हमें अपने एप्लिकेशन की वर्तमान स्थिति को ठीक करने की आवश्यकता है। क्योंकि हमें प्रदर्शन की परवाह है!

नोट: आधुनिक ब्राउज़रों में, न्यूनतम निष्पादन दर 4ms है जो फ्रेम दर के संदर्भ में लगभग 250fps है। यह Mozilla के वेब API डॉक्स के अनुसार है।

लेकिन इस विषय पर परस्पर विरोधी जानकारी है, अधिक जानकारी यहां।

एक फंक्शन "कितनी बार" निष्पादित होना चाहिए?

आदर्श फंक्शन निष्पादन दर संदर्भ पर निर्भर करती है। क्या हम एक विस्तृत एनिमेशन के साथ काम कर रहे हैं? या कुछ सरल, जैसे कुछ संख्यात्मक मान लौटाना (जैसे हम अपने ऐप के साथ करते हैं)?

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

हम एक प्रक्रिया का उपयोग करके निष्पादन आवृत्ति को नियंत्रित कर सकते हैं जिसे थ्रॉटलिंग कहा जाता है। यह आगे आ रहा है।

इवेंट थ्रॉटलिंग बचाव के लिए!

हम एक थ्रॉटलिंग फंक्शन का उपयोग करके प्रतिबंधित कर सकते हैं कि कोई अन्य फंक्शन समय के साथ कितनी बार निष्पादित होता है। उदाहरण: "इस फंक्शन को प्रति 100 ms केवल एक बार कॉल करें"।

आइए एक बेसिक इवेंट थ्रॉटलर फंक्शन पर एक नज़र डालें, जिसे विंडो रिसाइज इवेंट द्वारा ट्रिगर किया जाता है। थ्रॉटलर तब हर 100 ms पर एक बाहरी फंक्शन को कॉल करता है।

बेसिक थ्रॉटलर फंक्शन:

var throttled;
var delay = 100;
function functionToExecute() {
  console.log("निष्पादित!");
}
function throttler() {
  if (!throttled) {
    functionToExecute();
    throttled = true;
    setTimeout(function() {
      throttled = false;
    }, delay);
  }
}
window.addEventListener("resize", throttler);

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

इसे टेस्ट करने के लिए इस CodePen का उपयोग करें। आप देखेंगे कि हम functionToExecute() को प्रति सेकंड 10 बार तक कॉल करते हैं (10 x 100 = 1000 ms = 1 सेकंड)।

मैं अप टू कहता हूं क्योंकि एक फंक्शन हमेशा आपके द्वारा सेट की गई दर पर फायर नहीं करेगा। यह इस बात पर निर्भर करता है कि आपके फंक्शन के चलने के समय आपका हार्डवेयर कितना व्यस्त है। क्या आप अपने कंप्यूटर पर अन्य ऊर्जा-खपत वाले ऐप चला रहे हैं?।

थ्रॉटलर कोड में क्या हो रहा है:

चिंता न करें यदि आप इसे पहली बार नहीं समझते हैं। मैंने इस सामग्री के साथ बहुत समय बिताया जब तक कि यह अंततः क्लिक नहीं हुआ।

हमारी जावास्क्रिप्ट फ़ाइल के सबसे ऊपर, हम दो ग्लोबल वेरिएबल घोषित करके शुरू करते हैं:

var throttled; // खाली वेरिएबल। प्रकार: अपरिभाषित (फाल्सी मान)
var delay = 100; // संख्या

नोट: ग्लोबल वेरिएबल, का अर्थ है कि हम इन वेरिएबल को कहीं से भी एक्सेस कर सकते हैं।

हम throttled का उपयोग अपने throttler() फंक्शन के लिए एक संदर्भ बिंदु के रूप में करते हैं, यह जांचने के लिए कि क्या कतार में कोई फंक्शन निष्पादित करने के लिए है।

इससे पहले कि हमारा throttler() फंक्शन पहली बार ट्रिगर हो (रिसाइज इवेंट द्वारा), कतार में निष्पादित करने के लिए कोई फंक्शन नहीं होगा। तो throttled एक खाली वेरिएबल के रूप में शुरू होता है।

डिफ़ॉल्ट रूप से, खाली वेरिएबल का मान प्रकार अपरिभाषित होता है — जो एक फाल्सी मान प्रकार है। आप देखेंगे कि यह एक पल में क्यों महत्वपूर्ण है।

हम delay नामक एक वेरिएबल को एक संख्यात्मक मान (100) असाइन करते हैं। यह वह मान है जिसका उपयोग हम अपने throttler() फंक्शन के ms (मिलीसेकंड) निष्पादन दर को नियंत्रित करने के लिए करते हैं।

हम delay वेरिएबल को 100ms असाइन करते हैं। फिर हम उस वेरिएबल को हमारे थ्रॉटलर के setTimeout() में पास करते हैं। हमारा थ्रॉटलर तब हर 100ms या प्रति सेकंड 10 बार चलेगा — अधिकतम।

मैं अधिकतम कहता हूं क्योंकि 100ms हमारी निष्पादन दर पर एक कैप लगाता है। हमें वास्तव में प्रति सेकंड 10 से कम फंक्शन कॉल मिल सकते हैं, हमारे उपयोगकर्ता के हार्डवेयर और सॉफ़्टवेयर पर निर्भर करता है। लेकिन अधिकांश कंप्यूटर प्रति सेकंड 10 बार फायर करने में सक्षम होंगे।

थ्रॉटलर फंक्शन के अंदर, हम एक सशर्त if स्टेटमेंट सेट करते हैं:

function throttler() {
  if (!throttled) {
    // निष्पादित करने के लिए कोड
  }
}

सशर्त कथन जांचते हैं कि क्या एक निर्दिष्ट स्थिति का सच्चा मान है।

! प्रतीक का अर्थ नहीं है। तो if (!throttled) का अनुवाद है:

"यदि throttled के पास नहीं सच्चा मान है, तो if का कोड चलाएं।"

"लेकिन अगर throttled है सच्चा मान, तो वहीं रुक जाओ!"

जावास्क्रिप्ट में सही और गलत मान क्या हैं?

जावास्क्रिप्ट में, सच्चे और झूठे मान होते हैं। हाँ, उन्हें यही कहा जाता है। सच्चा एक मान है जो सच है। झूठा एक मान है जिसे झूठा माना जाता है (आश्चर्य!)।

जावास्क्रिप्ट में छह झूठे मान हैं:

  • अपरिभाषित
  • नल
  • 0
  • '' (खाली स्ट्रिंग)
  • NaN
  • false

जावास्क्रिप्ट में, ऊपर दिए गए मानों में से नहीं जो कुछ भी है उसे सच्चा मान माना जाता है। यह बहुत सरल है, है ना?

थ्रॉटलर पर वापस

सच बनाम झूठ पर उस त्वरित पाठ के साथ, आगे बढ़ें और जांचें कि क्या हमारा throttled वेरिएबल वास्तव में अपरिभाषित है, और एक झूठा मान प्रकार है।

हम console.log() का उपयोग करके !! का उपयोग करके अपने वेरिएबल की जल्दी से जांच कर सकते हैं:

var throttled;
console.log(throttled); // अपरिभाषित
console.log(!!throttled); // झूठा मान

!! एक डबल नहीं ऑपरेशन है। यह सच्चे और झूठे मानों की जांच करने का एक त्वरित तरीका है।

बहुत बढ़िया, अब हमने पुष्टि कर दी है कि throttled अपरिभाषित है, और एक झूठा मान प्रकार है। इसका मतलब है कि पहली बार जब हमारा throttler() चलता है, तो if की शर्त वास्तव में पूरी होती है।

// मैं एक झूठे मान के रूप में शुरू होता हूँ
var throttled;
// मुझे विंडो रिसाइज इवेंट द्वारा ट्रिगर किया जाता है
function throttler() {
  // मैं केवल अपना { कोड } चलाऊंगा अगर throttled झूठा है (यह है!)
  if (!throttled) {
    // निष्पादित करने के लिए कोड
  }
}

जिसका अर्थ है कि हम if के कोड ब्लॉक के अंदर क्या होता है उस पर आगे बढ़ सकते हैं।

if के कोड ब्लॉक के अंदर

if स्टेटमेंट कोड ब्लॉक के अंदर एक बार, हम तुरंत functionToExecute पर कॉलबैक शुरू करते हैं।

हम अपने ग्लोबल throttled वेरिएबल को भी true पर सेट करते हैं, इसलिए यह अब अपरिभाषित नहीं है (अब झूठा मान नहीं)। यह functionToExecute() के किसी भी भविष्य के कॉल को रोकता है।

if (!throttled) {
  // कॉलबैक चलाएं
  functionToExecute();
  // ग्लोबल throttled वेरिएबल को true पर सेट करें
  throttled = true;
  // ... 
}

लेकिन फिर ठीक नीचे, हम setTimeout का उपयोग करके 100ms देरी के बाद throttled मान को वापस झूठे मान पर रीसेट करते हैं:

function throttler() {
  if (!throttled) {
    // कॉलबैक चलाएं
    functionToExecute();
    // ग्लोबल throttled वेरिएबल को true पर सेट करें
    throttled = true;
    setTimeout(function() {
      // देरी के बाद throttled को वापस झूठा पर सेट करें
      throttled = false;
    }, delay);
  }
}

तो हर बार विंडो रिसाइज इवेंट चल रहा है, यह throttler() को ट्रिगर करता है, जो हर 100ms पर functionToExecute को कॉल करेगा!

थ्रॉटलिंग शक्ति है

थ्रॉटलिंग कितनी शक्तिशाली है, यह समझना आसान है अगर आप दो विपरीत चरम सीमाओं को देखते हैं। CodePen पर थ्रॉटलर फंक्शन में निम्नलिखित प्रयास करें:

  • 100 को 500 से बदलें और अपनी विंडो का आकार बदलें। ध्यान दें कि functionToExecute() को कितनी कम बार कॉल किया जाता है (प्रति सेकंड दो बार)।
  • फिर 500 को 16 से बदलने का प्रयास करें और विंडो का आकार बदलें। अब functionToExecute() कॉल से बमबारी हो रही है (प्रति सेकंड 60 कॉल तक)।

यही थ्रॉटलिंग काम करता है। हम इसका उपयोग समय के साथ फंक्शन को कितनी बार कॉल किया जा सकता है, इसे सीमित करने के लिए करते हैं। यह हार्डवेयर संसाधनों को बर्बाद करने से बचने का एक बहुत आसान तरीका है। कठिन हिस्सा एक दिए गए फंक्शन के लिए "इष्टतम" निष्पादन दर ढूंढना है, क्योंकि कोई भी प्रोजेक्ट समान नहीं है। इसके बारे में बाद में और अधिक।

थ्रॉटलर को हमारे प्रोजेक्ट में जोड़ना

थ्रॉटलर फंक्शन को अपने प्रोजेक्ट पर लागू करने के लिए, हमें पुराने कोड पर थोड़ा रीफैक्टरिंग करना होगा। रीफैक्टरिंग तब होता है जब हम प्रोग्राम की संरचना में सुधार करते हैं लेकिन समग्र कार्यक्षमता नहीं बदलते।

दूसरे शब्दों में: हम कुछ ऐसा लेते हैं जो पहले से काम करता है, और इसे उपयोग करना और समझना आसान बनाते हैं।

हम अब नहीं चाहते कि विंडो रिसाइज इवेंट सीधे चौड़ाई और ऊंचाई लौटाने वाले फंक्शन को निष्पादित करे। इसके बजाय, हम चाहते हैं कि हमारा थ्रॉटलर फंक्शन यह नियंत्रित करे कि कोड कब और कितनी बार निष्पादित होता है।

सौभाग्य से, परिवर्तन सरल है। हमें बस एक नामित फंक्शन घोषित करने की आवश्यकता है और फिर उस अनाम फंक्शन से सभी कोड को उस नामित फंक्शन के अंदर रखें।

आइए नए फंक्शन को getViewportDimensions() कहें:

function getViewportDimensions() {
  var width = window.innerWidth;
  var height = window.innerHeight;
  viewportDimensions.textContent = width + "px" + " x " + height + "px";
  viewportDimensions.style.display = "block";
  clearTimeout(resizeTimeout);
  resizeTimeout = setTimeout(removeViewportDimensions, 3000);
}

अब पहले से वही थ्रॉटलर फंक्शन लें, और functionToExecute() को getViewportDimensions() से बदलें:

function throttler() {
  if (!throttled) {
    // कॉलबैक: वह फंक्शन जिसे हम थ्रॉटल करना चाहते हैं
    getViewportDimensions();
    throttled = true;
    setTimeout(function() {
      throttled = false;
    }, delay);
  }
}

और अंत में हम विंडो रिसाइज इवेंट लिस्टनर जोड़ते हैं:

window.addEventListener("resize", throttler);

बस, सारा कठिन काम हो गया! समाप्त करने से पहले, आइए अपने ऐप के प्रदर्शन की जांच करें, और देखें कि क्या हमें कुछ ट्वीक करने की आवश्यकता है।

हार्डवेयर प्रदर्शन बनाम अनुभवजन्य प्रदर्शन

मुझे आपके बारे में पता नहीं, लेकिन जब मैं अपनी ब्राउज़र विंडो का आकार बदलता हूं, तो चौड़ाई और ऊंचाई की संख्या मेरी स्क्रीन पर थोड़ी धीमी रेंडर हो रही है। यह उतना स्मूथ नहीं है जितना थ्रॉटलर जोड़ने से पहले था।

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

इसमें कोई संदेह नहीं है कि हमारा ऐप हार्डवेयर उपयोग के दृष्टिकोण से बहुत प्रदर्शनकारी है। हमारा हार्डवेयर मुश्किल से कोई काम करता है, इसलिए यह अभी हमसे बिल्कुल प्यार करता है। जो अच्छा है।

लेकिन उपयोगकर्ता अनुभव के दृष्टिकोण से अनुभवजन्य प्रदर्शन के बारे में क्या? क्या हमारे उपयोगकर्ता भी हमसे प्यार करते हैं?

हमारा रेंडरिंग स्मूथ होना चाहिए। हमारी फंक्शन निष्पादन दर वर्तमान में 10 बार प्रति सेकंड पर सीमित है। आइए इसे बढ़ाएं। लेकिन कितना?

अगर हम पहले समय और फ्रेम दर के बीच संबंध को देखते हैं तो हम उस निर्णय को लेना आसान बना सकते हैं।

समय बनाम फ्रेम दर

फ्रेम दर को FPS (फ्रेम प्रति सेकंड) के रूप में भी जाना जाता है। यह प्रति सेकंड प्रदर्शित व्यक्तिगत फ्रेम की संख्या को संदर्भित करता है।

सामान्य तौर पर, FPS जितना अधिक होगा, रेंडरिंग उतनी ही स्मूथ होगी। वीडियो गेम को अक्सर स्मूथ रेंडर करने के लिए 60fps या अधिक की आवश्यकता होती है। अधिकांश फिल्में और टीवी श्रृंखला 24-30fps पर स्मूथ चलती हैं। वीडियो या ग्राफिक में जितना अधिक तेज़-तर्रार एक्शन होगा, उतने ही अधिक FPS की आवश्यकता होगी स्मूथ रेंडर करने के लिए।

कुछ प्रकार के ग्राफिक्स के लिए, आप 15fps जितना कम जा सकते हैं और फिर भी स्मूथ रेंडर प्राप्त कर सकते हैं। लेकिन आपको शायद ही कभी 15fps से नीचे जाना चाहिए क्योंकि तब अनुभवजन्य प्रदर्शन स्पष्ट रूप से धीमा दिखना शुरू हो जाएगा।

ms में अपने वांछित FPS को खोजने के लिए, आप अपने लक्ष्य fps को 1000 से विभाजित करते हैं, उदा। 1000/15(fps) = 66ms।

इस FPS से मिलीसेकंड टेबल पर एक नज़र डालें:

var 2fps = 1000/2; // 500ms
var 10fps = 1000/10; // 100ms
var 15fps = 1000/15; // 66ms
var 24fps = 1000/24; // 42ms
var 30fps = 1000/30; // 33ms
var 60fps = 1000/60; // 16ms

कुछ पहचानते हैं? हमारा ऐप वर्तमान में हर 100ms पर निष्पादित हो रहा है, या फ्रेम दर के संदर्भ में: 10 फ्रेम प्रति सेकंड।

याद रखें, मैंने अभी कहा था कि 15fps से नीचे कुछ भी आमतौर पर धीमा दिखाई देगा? यह बता सकता है कि वर्तमान ऐप का रेंडरिंग थोड़ा अजीब क्यों लगता है। स्मूथ रेंडर करने के लिए प्रति सेकंड पर्याप्त फ्रेम नहीं हैं। यह तत्काल महसूस नहीं होता।

आइए कुछ टेस्टिंग करते हैं

मैं गारंटी देता हूं कि अगर हम अपने व्यूपोर्ट आयाम फीचर को 15fps (66ms) पर चलाने के लिए क्रैंक करते हैं, तो यह वर्तमान 10fps (100ms) की तुलना में काफी स्मूथ दिखेगा।

और यह बहुत अधिक अतिरिक्त CPU शक्ति खर्च नहीं करेगा।

हमें केवल इसे पर्याप्त स्मूथ होने की आवश्यकता है।

जैसा कि मैंने पहले कहा, विपरीत चरम सीमाओं का परीक्षण करना यह पता लगाने का एक अच्छा तरीका है कि क्या नहीं करना है। फिर सवाल बन जाता है कि दो चरम सीमाओं के बीच कहां आपका प्रोजेक्ट फिट बैठता है?

अपने व्यूपोर्ट आयाम ऐप पर निम्नलिखित फ्रेम दरों का परीक्षण करने का प्रयास करें: 5fps (500ms), 15fps (66ms), और 60fps (16ms) और देखें क्या होता है।

आप क्या सोचते हैं?

5fps भयानक लगता है। यह टूटा हुआ लगता है। यह कभी काम नहीं करेगा। हमारा हार्डवेयर इसे पसंद करेगा, लेकिन हमारे उपयोगकर्ता इससे नफरत करेंगे!

15fps मुझे अच्छा लगता है। मैं यह नहीं कहूंगा कि यह फ्रेम दर 100% स्मूथ है, लेकिन यह स्पष्ट रूप से 10fps से बेहतर है।

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

60fps सुपर स्मूथ है — आश्चर्य की बात नहीं। लेकिन ईमानदारी से, यह बड़े पैमाने पर अतिरिक्त हार्डवेयर उपयोग के लायक नहीं है।

मैं अपने ऐप के लिए 15fps पर समझौता करने जा रहा हूँ।

15 FPS क्यों?

मैंने 15fps / 66ms पर फैसला करने का कारण यह है कि यह फ्रेम दर अधिकांश लोगों द्वारा अनुभव की जाने वाली स्मूथ होने के लिए पर्याप्त उच्च है।

अधिकांश सॉफ़्टवेयर, कंप्यूटर, और डिस्प्ले (स्क्रीन) बिना किसी समस्या के 15fps पर रेंडर कर सकते हैं। यहां तक कि अधिकांश छोटे, हैंडहेल्ड डिवाइस बिना किसी समस्या के 15fps को संभाल सकते हैं।

उच्च फ्रेम दरों का विरोधाभास यह है कि जबकि तर्क हमें बताता है कि अधिक फ्रेम प्रति सेकंड = स्मूथ, इसका विपरीत प्रभाव भी हो सकता है।

यदि आप अपने उपयोगकर्ता के हार्डवेयर और सॉफ़्टवेयर द्वारा संभाले जा सकने वाले फ्रेम दर या रिफ्रेश रेट को लागू करने का प्रयास करते हैं, तो परिणाम अक्सर होता है: लैगिंग।

रिफ्रेश रेट: यह है कि आपका डिस्प्ले आपकी स्क्रीन को कितनी बार रीड्रॉ कर सकता है। 45Hz की रिफ्रेश रेट का मतलब है कि आपका डिस्प्ले अपनी पूरी स्क्रीन को 1 सेकंड में 45 बार रीड्रॉ कर सकता है।

अब यदि आपका CPU और GPU 60fps की फ्रेम दर उत्पन्न कर सकता है, लेकिन आपके डिस्प्ले की रिफ्रेश रेट केवल 45Hz है, तो आपके पास एक बेमेल है। यह अक्सर अप्रत्याशित परिणामों का कारण बनता है।

हम डेवलपर्स और डिज़ाइनर आसानी से वास्तविकता से संपर्क खो सकते हैं। हमारी विकास मशीनें आमतौर पर औसत व्यक्ति के कंप्यूटर से अधिक शक्तिशाली होती हैं।

यही कारण है कि हमें बाजार में उत्पादों को पुश करने से पहले ठोस शोध करने और अपनी मान्यताओं का परीक्षण करने की आवश्यकता है।

तो 15fps एक खुशहाल माध्यम है जो उन लोगों के लिए भी काम करेगा जिनके पास शक्तिशाली मशीनें नहीं हैं।

थ्रॉटलर जोड़ने से पहले हमारे हार्डवेयर द्वारा उपयोग की गई ऊर्जा का कम से कम 75% बचाने के लिए 15fps का उपयोग भी करेगा।

15fps से नीचे कुछ भी आमतौर पर धीमा और लैगी दिखना शुरू हो जाएगा। यह वास्तव में स्पष्ट हो जाता है जब आप लगभग 10fps पर पहुंच जाते हैं, यही कारण है कि हमारी प्रारंभिक फ्रेम दर पर्याप्त नहीं थी।

प्रतिक्रिया समय के विषय पर एक अंतर्दृष्टिपूर्ण वीडियो जो 15fps से नीचे न जाने के मेरे तर्क का समर्थन करता है (अधिकांश चीजों पर)।

संदर्भ और न्यूनतम प्रभावी खुराक

15 से 30fps तक अनुभवजन्य अंतर कितना है? अगर आप इसे हमारे द्वारा अभी बनाए गए ऐप पर टेस्ट करते हैं, तो आप आश्चर्यचकित होंगे।

आप शायद किसी महत्वपूर्ण अंतर को नोटिस नहीं कर पाएंगे। कोई डील-ब्रेकिंग अंतर नहीं। लेकिन हार्डवेयर उपयोग के लिए आप जो कीमत चुकाते हैं वह दोगुनी हो जाती है!

उच्च fps बहुत हार्डवेयर शक्ति खर्च करता है। तो जरूरत से ज्यादा क्यों उपयोग करें? हमेशा घटते रिटर्न का एक बिंदु होता है। यहीं पर न्यूनतम प्रभावी खुराक (MED) आती है। आपको केवल पर्याप्त चाहिए, वांछित प्रभाव प्राप्त करने के लिए, न अधिक, न कम।

बेशक, यह हमेशा संदर्भ पर निर्भर करता है। क्या हम एक विस्फोटक फर्स्ट-पर्सन शूटर वीडियो गेम के बारे में बात कर रहे हैं या हमारे द्वारा बनाए गए एक साधारण पिक्सेल काउंटर के बारे में? संदर्भ कुंजी है!

फिनिशिंग टच

सारा कठिन काम हो गया। अच्छे उपाय के लिए, आइए अपने सभी कोड को एक IIFE ((function () {...})();) के अंदर लपेटें और अंदर use strict मोड इनिशियलाइज़ करें:

(function() {
  "use strict";
  // अपना सारा कोड नीचे रखें
})();

IIFE (तत्काल-आह्वान फंक्शन एक्सप्रेशन), आपके सभी कोड को स्थानीय स्कोप के अंदर रखता है।

यदि हम अपने कोड को इस तरह नहीं लपेटते हैं, तो हम "ग्लोबल नेमस्पेस को प्रदूषित करने" का जोखिम उठाते हैं। यह यह कहने का एक फैंसी तरीका है कि हम अपने ऐप के बाहर अन्य कोड के साथ विरोधाभास पैदा करने का जोखिम उठाते हैं।

use strict; का उपयोग 3rd पार्टी सॉफ़्टवेयर के साथ विरोधाभास को रोकने के लिए भी किया जाता है जो सख्त कोडिंग नियमों का पालन नहीं करते हैं।

हमारा काम पूरा हुआ!

यहां वह सभी कोड है जो हमने लिखा है। मैंने स्पष्टीकरण के लिए कुछ टिप्पणियां और पठनीयता के लिए कुछ अतिरिक्त व्हाइट स्पेस जोड़े हैं:

पूर्ण प्रोजेक्ट कोड:

(function() {
  "use strict";
  // विंडो इवेंट शुरू होने से पहले throttled मान
  var throttled;
  // फंक्शन कॉल को 66ms (फ्रेम दर: 15fps) तक विलंबित करें
  var delay = 66;
  // बाद में उपयोग के लिए खाली वेरिएबल घोषित करें
  var resizeTimeout;
  // बॉडी एलिमेंट पकड़ें
  var body = document.querySelector("body");
  // एलिमेंट बनाएं
  var viewportDimensions = document.createElement("div");
  // एलिमेंट स्टाइल करें
  viewportDimensions.style.position = "fixed";
  viewportDimensions.style.right = 0;
  viewportDimensions.style.top = 0;
  viewportDimensions.style.padding = "16px";
  viewportDimensions.style.zIndex = 3;
  viewportDimensions.style.fontSize = "22px";
  // div एलिमेंट को बॉडी एलिमेंट के अंदर जोड़ें
  body.appendChild(viewportDimensions);
  // window.resize कॉलबैक फंक्शन
  function getViewportDimensions() {
    var width = window.innerWidth;
    var height = window.innerHeight;
    viewportDimensions.textContent = width + "px" + " x " + height + "px";
    viewportDimensions.style.display = "block";
    clearTimeout(resizeTimeout);
    resizeTimeout = setTimeout(removeViewportDimensions, 3000);
  }
  // getViewportDimensions() से कॉल किया गया
  function removeViewportDimensions() {
    viewportDimensions.style.display = "none";
  }
  function throttler() {
    // केवल if के ब्लॉक को चलाएं अगर हम थ्रॉटल नहीं हैं
    if (!throttled) {
      // कॉलबैक: वह फंक्शन जिसे हम थ्रॉटल करना चाहते हैं
      getViewportDimensions();
      // हम वर्तमान में थ्रॉटल हैं!
      throttled = true;
      // देरी के बाद throttled वेरिएबल को वापस झूठा पर रीसेट करें
      setTimeout(function() {
        throttled = false;
      }, delay);
    }
  }
  // रिसाइज इवेंट सुनें, और throttler() चलाएं
  window.addEventListener("resize", throttler);
  // IIFE रैपर का अंत
})();

यहां एक CodePen है जिसके साथ आप खेल सकते हैं।

अपने ऐप को किसी भी प्रोजेक्ट पर कैसे उपयोग करें

अपने HTML दस्तावेज़ के नीचे, अपने क्लोजिंग बॉडी टैग (</body>) के ठीक ऊपर एक स्क्रिप्ट टैग शामिल करें, और अपने js फ़ाइल का पथ जोड़ें, जैसे:

&lt;script src="/js/get-viewport-dimensions.js"&gt;&lt;/script&gt;

ब्राउज़र संगतता

हमारा ऐप सभी आधुनिक ब्राउज़रों के साथ संगत है, और इंटरनेट एक्सप्लोरर 9 और ऊपर से।

उन्नत थ्रॉटलिंग

इस ट्यूटोरियल में हमने जो सीखा वह बाजार पर कुछ अधिक शक्तिशाली प्रदर्शन टूल के लिए एक बेहतरीन अग्रदूत है।

यदि आपको हमारे द्वारा बनाए गए प्रोजेक्ट से अधिक जटिल प्रोजेक्ट पर प्रदर्शन बढ़ाने की आवश्यकता है, तो Lodash जावास्क्रिप्ट लाइब्रेरी देखें। Lodash में बहुत सारी प्रदर्शन विशेषताएं हैं और डेवलपर्स के बीच बहुत लोकप्रिय है। आप लाइब्रेरी के कोड को खोदकर भी बहुत कुछ सीख सकते हैं।

संसाधन

  • Mozilla का रिसाइज इवेंट डॉक्स
  • Mozilla का फ्रेम दर डॉक्स
  • प्रतिक्रिया समय पर वीडियो
  • फ्रेम दर बनाम रिफ्रेश दर
  • setTimeout का उपयोग करते समय 66ms क्यों
  1. JavaScript unescape() उदाहरण के साथ JavaScript unescape() उदाहरण के साथ

    JavaScript unescape() फंक्शन का उपयोग एन्कोडेड स्ट्रिंग को डीकोड करने के लिए किया जाता है। यह JavaScript वर्जन 1.5 में डिप्रिकेटेड है।उदाहरण<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="wi

  1. जावास्क्रिप्ट call() मेथड आर्गुमेंट्स के साथ जावास्क्रिप्ट call() मेथड आर्गुमेंट्स के साथ

    परिचय जावास्क्रिप्ट call() मेथड हमें एक ही मेथड को अलग-अलग ऑब्जेक्ट्स के साथ उपयोग करने की अनुमति देता है। पैरामीटर्स को अलग-अलग पास किया जाता है (कॉमा-सेपरेटेड)। यह this को स्पष्ट रूप से सेट करता है। apply() समान है लेकिन आर्गुमेंट्स को ऐरे के रूप में लेता है। bind() एक नया फ़ंक्शन लौटाता है जिसमे

  1. उदाहरण के साथ जावास्क्रिप्ट में इनहेरिटेंस उदाहरण के साथ जावास्क्रिप्ट में इनहेरिटेंस

    जावास्क्रिप्ट एक ऑब्जेक्ट-आधारित भाषा है जो प्रोटोटाइप पर आधारित है। इनहेरिटेंस को जावास्क्रिप्ट में प्रोटोटाइप ऑब्जेक्ट का उपयोग करके लागू किया जाता है। जावास्क्रिप्ट में इनहेरिटेंस लागू करने के लिए कोड निम्नलिखित है: उदाहरण <!DOCTYPE html> <html lang=en> <head> <meta charset=