लंबे टास्क ऑप्टिमाइज़ करें

आपको "मुख्य थ्रेड को ब्लॉक न करने" और "ज़्यादा समय लेने वाले कामों को छोटे-छोटे हिस्सों में बांटने" के लिए कहा गया है. हालांकि, इन कामों को करने का क्या मतलब है?

पब्लिश होने की तारीख: 30 सितंबर, 2022, पिछली बार अपडेट किए जाने की तारीख: 19 दिसंबर, 2024

JavaScript ऐप्लिकेशन को तेज़ी से काम करने लायक बनाए रखने के लिए, आम तौर पर यह सलाह दी जाती है:

  • "मुख्य थ्रेड को ब्लॉक न करें."
  • "ज़्यादा समय लेने वाले कामों को छोटे-छोटे हिस्सों में बांटें."

यह बहुत अच्छी सलाह है, लेकिन इसके लिए क्या करना होगा? कम JavaScript भेजना अच्छा है. हालांकि, क्या इससे यूज़र इंटरफ़ेस अपने-आप ज़्यादा रिस्पॉन्सिव हो जाता है? शायद हां, शायद नहीं.

JavaScript में टास्क को ऑप्टिमाइज़ करने का तरीका समझने के लिए, आपको सबसे पहले यह जानना होगा कि टास्क क्या होते हैं और ब्राउज़र उन्हें कैसे मैनेज करता है.

टास्क क्या होता है?

टास्क, ब्राउज़र का कोई भी अलग काम होता है. इस काम में रेंडरिंग, एचटीएमएल और सीएसएस को पार्स करना, JavaScript चलाना, और अन्य तरह के काम शामिल हैं. ऐसा हो सकता है कि इन पर आपका सीधा कंट्रोल न हो. इन सभी में से, आपका लिखा गया JavaScript शायद टास्क का सबसे बड़ा सोर्स है.

Chrome के DevTools के परफ़ॉर्मेंस प्रोफ़ाइलर में दिखाए गए टास्क का विज़ुअलाइज़ेशन. टास्क, स्टैक में सबसे ऊपर है. इसके नीचे, क्लिक इवेंट हैंडलर, फ़ंक्शन कॉल, और अन्य आइटम मौजूद हैं. इस टास्क में, दाईं ओर रेंडरिंग का कुछ काम भी शामिल है.
Chrome DevTools के परफ़ॉर्मेंस प्रोफ़ाइलर में दिखाया गया, click इवेंट हैंडलर से शुरू किया गया टास्क.

JavaScript से जुड़े टास्क, परफ़ॉर्मेंस पर कई तरह से असर डालते हैं:

  • जब कोई ब्राउज़र स्टार्टअप के दौरान JavaScript फ़ाइल डाउनलोड करता है, तो वह उस JavaScript को पार्स और कंपाइल करने के लिए टास्क को सूची में डालता है, ताकि उसे बाद में चलाया जा सके.
  • पेज के लाइफ़साइकल के दौरान, टास्क को सूची में तब रखा जाता है, जब JavaScript काम करता है. जैसे, इवेंट हैंडलर के ज़रिए इंटरैक्शन का जवाब देना, JavaScript से चलने वाले ऐनिमेशन, और बैकग्राउंड में होने वाली गतिविधि, जैसे कि आंकड़ों का कलेक्शन.

वेब वर्कर और मिलते-जुलते एपीआई को छोड़कर, यह सब मुख्य थ्रेड पर होता है.

मुख्य थ्रेड क्या है?

मुख्य थ्रेड वह जगह है जहां ब्राउज़र में ज़्यादातर टास्क चलते हैं. साथ ही, यहां आपकी लिखी गई ज़्यादातर JavaScript को एक्ज़ीक्यूट किया जाता है.

मुख्य थ्रेड, एक बार में सिर्फ़ एक टास्क को प्रोसेस कर सकता है. जिस टास्क को पूरा होने में 50 मिलीसेकंड से ज़्यादा समय लगता है उसे ज़्यादा समय लेने वाला टास्क कहा जाता है. अगर किसी टास्क को पूरा होने में 50 मिलीसेकंड से ज़्यादा समय लगता है, तो टास्क को पूरा होने में लगे कुल समय में से 50 मिलीसेकंड घटाने पर जो समय बचता है उसे टास्क का ब्लॉकिंग पीरियड कहा जाता है.

ब्राउज़र, किसी भी टास्क के चलने के दौरान इंटरैक्शन को ब्लॉक कर देता है. हालांकि, जब तक टास्क बहुत ज़्यादा समय तक नहीं चलते, तब तक उपयोगकर्ता को इसका पता नहीं चलता. हालांकि, जब कोई उपयोगकर्ता किसी ऐसे पेज से इंटरैक्ट करने की कोशिश करता है जिसमें ज़्यादा समय लेने वाले कई काम होते हैं, तो यूज़र इंटरफ़ेस काम नहीं करता. इसके अलावा, अगर मुख्य थ्रेड को बहुत लंबे समय तक ब्लॉक किया जाता है, तो हो सकता है कि वह काम न करे.

Chrome के DevTools के परफ़ॉर्मेंस प्रोफ़ाइलर में ज़्यादा समय लेने वाला काम. टास्क के ब्लॉक करने वाले हिस्से (50 मिलीसेकंड से ज़्यादा) को लाल रंग की तिरछी पट्टियों के पैटर्न से दिखाया जाता है.
Chrome के परफ़ॉर्मेंस प्रोफ़ाइलर में दिखाया गया ज़्यादा समय लेने वाला काम. ज़्यादा समय लेने वाले टास्क, टास्क के कोने में लाल रंग के त्रिभुज से दिखाए जाते हैं. साथ ही, टास्क के ब्लॉक करने वाले हिस्से को लाल रंग की तिरछी पट्टियों के पैटर्न से भरा जाता है.

मुख्य थ्रेड को ज़्यादा समय तक ब्लॉक होने से बचाने के लिए, ज़्यादा समय लेने वाले काम को कई छोटे-छोटे कामों में बांटा जा सकता है.

ज़्यादा समय लेने वाले एक टास्क और उसी टास्क को छोटे-छोटे टास्क में बांटने के बीच का अंतर. ज़्यादा समय लेने वाले काम को एक बड़े रेक्टैंगल के तौर पर दिखाया गया है. वहीं, छोटे-छोटे हिस्सों में बंटे काम को पांच छोटे बॉक्स के तौर पर दिखाया गया है. इन बॉक्स की कुल चौड़ाई, ज़्यादा समय लेने वाले काम की चौड़ाई के बराबर है.
एक लंबे टास्क और उसी टास्क को पांच छोटे टास्क में बांटकर दिखाया गया है.

यह ज़रूरी है, क्योंकि टास्क को छोटे-छोटे हिस्सों में बांटने से, ब्राउज़र ज़्यादा प्राथमिकता वाले टास्क को जल्दी पूरा कर सकता है. इनमें उपयोगकर्ता के इंटरैक्शन भी शामिल हैं. इसके बाद, बाकी टास्क पूरे किए जाते हैं. इससे यह पक्का होता है कि आपने शुरुआत में जो काम सूची में जोड़े थे वे पूरे हो जाएं.

इस इमेज में दिखाया गया है कि किसी टास्क को छोटे-छोटे हिस्सों में बांटने से, उपयोगकर्ता के इंटरैक्शन को कैसे आसान बनाया जा सकता है. सबसे ऊपर, ज़्यादा समय लेने वाला एक टास्क, इवेंट हैंडलर को तब तक चलने से रोकता है, जब तक कि टास्क पूरा नहीं हो जाता. सबसे नीचे, छोटे-छोटे हिस्सों में बंटे टास्क की वजह से, इवेंट हैंडलर को सामान्य से ज़्यादा तेज़ी से चलने की अनुमति मिलती है.
इस विज़ुअलाइज़ेशन में दिखाया गया है कि जब टास्क बहुत लंबे होते हैं और ब्राउज़र, इंटरैक्शन का तुरंत जवाब नहीं दे पाता है, तो इंटरैक्शन पर क्या असर पड़ता है. साथ ही, यह भी दिखाया गया है कि जब लंबे टास्क को छोटे टास्क में बांट दिया जाता है, तो क्या होता है.

ऊपर दी गई इमेज में सबसे ऊपर, उपयोगकर्ता के इंटरैक्शन से सूची में जोड़े गए इवेंट हैंडलर को शुरू होने से पहले, ज़्यादा समय लेने वाले एक काम के पूरा होने का इंतज़ार करना पड़ा. इससे इंटरैक्शन में देरी होती है. इस स्थिति में, हो सकता है कि उपयोगकर्ता को लैग दिखा हो. सबसे नीचे, इवेंट हैंडलर जल्दी चलना शुरू हो सकता है और इंटरैक्शन तुरंत महसूस हो सकता है.

अब आपको पता चल गया है कि टास्क को छोटे-छोटे हिस्सों में बांटना क्यों ज़रूरी है. इसलिए, JavaScript में ऐसा करने का तरीका जानें.

टास्क मैनेज करने की रणनीतियां

सॉफ़्टवेयर आर्किटेक्चर में एक आम सलाह यह दी जाती है कि अपने काम को छोटे-छोटे फ़ंक्शन में बांट लें:

function saveSettings () {
  validateForm();
  showSpinner();
  saveToDatabase();
  updateUI();
  sendAnalytics();
}

इस उदाहरण में, saveSettings() नाम का एक फ़ंक्शन है, जो पांच फ़ंक्शन को कॉल करता है. ये फ़ंक्शन, फ़ॉर्म की पुष्टि करने, स्पिनर दिखाने, ऐप्लिकेशन बैकएंड को डेटा भेजने, यूज़र इंटरफ़ेस को अपडेट करने, और आंकड़े भेजने के लिए हैं.

कॉन्सेप्ट के हिसाब से, saveSettings() को अच्छी तरह से डिज़ाइन किया गया है. अगर आपको इनमें से किसी फ़ंक्शन को डीबग करना है, तो प्रोजेक्ट ट्री को एक्सप्लोर करके यह पता लगाया जा सकता है कि हर फ़ंक्शन क्या करता है. इस तरह से काम को बांटने से, प्रोजेक्ट को मैनेज करना और उन्हें समझना आसान हो जाता है.

हालांकि, यहां एक समस्या यह हो सकती है कि JavaScript इनमें से हर फ़ंक्शन को अलग-अलग टास्क के तौर पर नहीं चलाता. ऐसा इसलिए होता है, क्योंकि इन्हें saveSettings() फ़ंक्शन के अंदर चलाया जाता है. इसका मतलब है कि ये पांचों फ़ंक्शन एक ही टास्क के तौर पर चलेंगे.

Chrome के परफ़ॉर्मेंस प्रोफ़ाइलर में दिखाया गया saveSettings फ़ंक्शन. टॉप-लेवल फ़ंक्शन, पांच अन्य फ़ंक्शन को कॉल करता है. हालांकि, सारा काम एक ही टास्क में होता है. इस वजह से, फ़ंक्शन को चलाने का नतीजा तब तक नहीं दिखता, जब तक सभी टास्क पूरे नहीं हो जाते.
एक फ़ंक्शन saveSettings() जो पांच फ़ंक्शन को कॉल करता है. यह काम एक लंबे टास्क के तौर पर किया जाता है. इसमें पांचों फ़ंक्शन पूरे होने तक, कोई भी विज़ुअल रिस्पॉन्स नहीं दिखता.

सबसे अच्छी स्थिति में, इनमें से सिर्फ़ एक फ़ंक्शन, टास्क की कुल अवधि में 50 मिलीसेकंड या उससे ज़्यादा का योगदान दे सकता है. सबसे खराब स्थिति में, इनमें से ज़्यादा टास्क ज़्यादा समय तक चल सकते हैं. खास तौर पर, कम संसाधनों वाले डिवाइसों पर.

इस मामले में, saveSettings() को उपयोगकर्ता के क्लिक से ट्रिगर किया जाता है. ब्राउज़र तब तक जवाब नहीं दिखा पाता, जब तक पूरा फ़ंक्शन चलना बंद नहीं हो जाता. ज़्यादा समय लेने वाले इस काम की वजह से, यूज़र इंटरफ़ेस (यूआई) धीमा हो जाता है और जवाब नहीं देता. साथ ही, इसे पेज के रिस्पॉन्स में लगने वाले समय (आईएनपी) के खराब स्कोर के तौर पर मेज़र किया जाएगा.

मैन्युअल तरीके से कोड एक्ज़ीक्यूशन को रोकना

उपयोगकर्ता के लिए ज़रूरी टास्क और यूज़र इंटरफ़ेस (यूआई) के रिस्पॉन्स, कम प्राथमिकता वाले टास्क से पहले हों, यह पक्का करने के लिए मुख्य थ्रेड को प्राथमिकता दें. इसके लिए, अपने काम को कुछ समय के लिए रोकें, ताकि ब्राउज़र को ज़्यादा ज़रूरी टास्क चलाने का मौका मिल सके.

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

function saveSettings () {
  // Do critical work that is user-visible:
  validateForm();
  showSpinner();
  updateUI();

  // Defer work that isn't user-visible to a separate task:
  setTimeout(() => {
    saveToDatabase();
    sendAnalytics();
  }, 0);
}

इसे यील्डिंग कहा जाता है. यह उन फ़ंक्शन की सीरीज़ के लिए सबसे सही तरीका है जिन्हें क्रम से चलाना ज़रूरी है.

हालांकि, ऐसा हो सकता है कि आपका कोड हमेशा इस तरह से व्यवस्थित न हो. उदाहरण के लिए, आपके पास बहुत सारा डेटा हो सकता है जिसे लूप में प्रोसेस करना ज़रूरी है. अगर कई बार दोहराव होता है, तो उस टास्क को पूरा होने में बहुत ज़्यादा समय लग सकता है.

function processData () {
  for (const item of largeDataArray) {
    // Process the individual item here.
  }
}

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

setTimeout का इस्तेमाल करने पर, एक और समस्या आती है: जब setTimeout का इस्तेमाल करके, कोड को बाद के टास्क में चलाने के लिए रोक दिया जाता है, तो वह टास्क सूची के आखिर में जुड़ जाता है. अगर अन्य टास्क बाकी हैं, तो वे आपके रोके गए कोड से पहले चलेंगे.

एक खास यील्डिंग एपीआई: scheduler.yield()

Browser Support

  • Chrome: 129.
  • Edge: 129.
  • Firefox: 142.
  • Safari: not supported.

Source

scheduler.yield() एक ऐसा एपीआई है जिसे खास तौर पर ब्राउज़र में मुख्य थ्रेड को यील्ड करने के लिए डिज़ाइन किया गया है.

यह भाषा के लेवल का सिंटैक्स या कोई खास कंस्ट्रक्ट नहीं है. scheduler.yield() सिर्फ़ एक फ़ंक्शन है, जो Promise दिखाता है. इसे आने वाले समय में किसी टास्क में रिज़ॉल्व किया जाएगा. Promise के रिज़ॉल्व होने के बाद, रन करने के लिए चेन किया गया कोई भी कोड (साफ़ तौर पर .then() चेन में या एसिंक फ़ंक्शन में await करने के बाद), आने वाले समय में उस टास्क में रन होगा.

प्रैक्टिकल तौर पर: await scheduler.yield() डालें. इससे फ़ंक्शन उस पॉइंट पर रुक जाएगा और मुख्य थ्रेड पर चला जाएगा. फ़ंक्शन के बाकी हिस्से को एक्ज़ीक्यूट करने के लिए, उसे नए इवेंट-लूप टास्क में शेड्यूल किया जाएगा. इसे फ़ंक्शन का कंटिन्यूएशन कहा जाता है. जब वह टास्क शुरू होगा, तो इंतज़ार कर रहा प्रॉमिस रिज़ॉल्व हो जाएगा और फ़ंक्शन वहीं से फिर से शुरू हो जाएगा जहां उसे छोड़ा गया था.

async function saveSettings () {
  // Do critical work that is user-visible:
  validateForm();
  showSpinner();
  updateUI();

  // Yield to the main thread:
  await scheduler.yield()

  // Work that isn't user-visible, continued in a separate task:
  saveToDatabase();
  sendAnalytics();
}
Chrome के परफ़ॉर्मेंस प्रोफ़ाइलर में दिखाया गया saveSettings फ़ंक्शन, अब दो टास्क में बंटा हुआ है. पहले टास्क में दो फ़ंक्शन को कॉल किया जाता है. इसके बाद, यह टास्क यील्ड करता है, ताकि लेआउट और पेंट का काम हो सके और उपयोगकर्ता को जवाब दिख सके. इस वजह से, क्लिक इवेंट 64 मिलीसेकंड में पूरा हो जाता है. दूसरा टास्क, आखिरी तीन फ़ंक्शन को कॉल करता है.
saveSettings() फ़ंक्शन को लागू करने की प्रोसेस को अब दो टास्क में बांट दिया गया है. इस वजह से, टास्क के बीच में लेआउट और पेंट को चलाया जा सकता है. इससे उपयोगकर्ता को तेज़ी से विज़ुअल रिस्पॉन्स मिलता है. इसे अब पॉइंटर इंटरैक्शन के ज़रिए मेज़र किया जाता है.

हालांकि, यील्ड करने के अन्य तरीकों के मुकाबले scheduler.yield() का असली फ़ायदा यह है कि इसमें टास्क को जारी रखने को प्राथमिकता दी जाती है. इसका मतलब है कि अगर किसी टास्क के बीच में यील्ड किया जाता है, तो मौजूदा टास्क को जारी रखने की प्रोसेस, मिलते-जुलते अन्य टास्क शुरू होने से पहले चलेगी.

इससे, टास्क के अन्य सोर्स से मिलने वाले कोड, आपके कोड के एक्ज़ीक्यूशन के क्रम में रुकावट नहीं डालते. जैसे, तीसरे पक्ष की स्क्रिप्ट से मिलने वाले टास्क.

तीन डायग्राम, जिनमें टास्क को बिना यील्ड, यील्ड, और यील्ड और कंटिन्यूएशन के साथ दिखाया गया है. यील्डिंग के बिना, ज़्यादा समय लेने वाले टास्क होते हैं. यील्डिंग की मदद से, छोटे-छोटे टास्क ज़्यादा होते हैं. हालांकि, इनमें अन्य टास्क की वजह से रुकावट आ सकती है. यील्डिंग और कंटिन्यूएशन की मदद से, छोटे-छोटे टास्क ज़्यादा होते हैं. हालांकि, उनके एक्ज़ीक्यूशन का क्रम बरकरार रहता है.
scheduler.yield() का इस्तेमाल करने पर, यह अन्य टास्क पर जाने से पहले, वहीं से शुरू होता है जहाँ आपने इसे छोड़ा था.

क्रॉस-ब्राउज़र सपोर्ट

scheduler.yield() फ़िलहाल सभी ब्राउज़र पर काम नहीं करता. इसलिए, फ़ॉलबैक की ज़रूरत होती है.

इसका एक तरीका यह है कि अपने बिल्ड में scheduler-polyfill को छोड़ दें. इसके बाद, scheduler.yield() का इस्तेमाल सीधे तौर पर किया जा सकता है. पॉलीफ़िल, टास्क शेड्यूल करने वाले अन्य फ़ंक्शन पर वापस जाने की प्रोसेस को मैनेज करेगा, ताकि यह सभी ब्राउज़र पर एक जैसा काम करे.

इसके अलावा, कुछ लाइनों में एक आसान वर्शन लिखा जा सकता है. इसके लिए, सिर्फ़ setTimeout का इस्तेमाल करें. इसे Promise में रैप करें, ताकि scheduler.yield() उपलब्ध न होने पर इसे फ़ॉलबैक के तौर पर इस्तेमाल किया जा सके.

function yieldToMain () {
  if (globalThis.scheduler?.yield) {
    return scheduler.yield();
  }

  // Fall back to yielding with setTimeout.
  return new Promise(resolve => {
    setTimeout(resolve, 0);
  });
}

जिन ब्राउज़र में scheduler.yield() की सुविधा नहीं है उन्हें प्राथमिकता के आधार पर जारी रखने की सुविधा नहीं मिलेगी. हालांकि, वे ब्राउज़र के रिस्पॉन्सिव बने रहने के लिए अब भी काम करेंगे.

आखिर में, कुछ ऐसे मामले हो सकते हैं जहां आपका कोड मुख्य थ्रेड को कंट्रोल नहीं दे सकता. ऐसा तब होता है, जब उसके जारी रहने को प्राथमिकता न दी गई हो. उदाहरण के लिए, कोई ऐसा पेज जो पहले से ही व्यस्त हो और जहां कंट्रोल देने से कुछ समय के लिए काम पूरा न होने का जोखिम हो. ऐसे में, scheduler.yield() को एक तरह की परतदार वृद्धि के तौर पर माना जा सकता है: उन ब्राउज़र में नतीजे दें जहां scheduler.yield() उपलब्ध है, नहीं तो जारी रखें.

ऐसा करने के लिए, सुविधा का पता लगाया जा सकता है और एक लाइन में लिखे गए कोड की मदद से, एक माइक्रोटास्क के लिए इंतज़ार किया जा सकता है:

// Yield to the main thread if scheduler.yield() is available.
await globalThis.scheduler?.yield?.();

scheduler.yield() की मदद से, लंबे समय तक चलने वाले काम को छोटे-छोटे हिस्सों में बांटें

scheduler.yield() का इस्तेमाल करने के लिए, इनमें से किसी भी तरीके का इस्तेमाल करने का फ़ायदा यह है कि इसे किसी भी async फ़ंक्शन में await किया जा सकता है.

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

async function runJobs(jobQueue) {
  for (const job of jobQueue) {
    // Run the job:
    job();

    // Yield to the main thread:
    await yieldToMain();
  }
}

runJobs() को जारी रखने को प्राथमिकता दी जाएगी. हालांकि, ज़्यादा प्राथमिकता वाले काम को भी अनुमति दी जाएगी. जैसे, उपयोगकर्ता के इनपुट का विज़ुअल तौर पर जवाब देना. इसके लिए, नौकरियों की लंबी सूची के खत्म होने का इंतज़ार नहीं करना पड़ेगा.

हालांकि, यह यील्डिंग का बेहतर इस्तेमाल नहीं है. scheduler.yield() तेज़ और असरदार है, लेकिन इसमें कुछ ओवरहेड भी है. अगर jobQueue में कुछ जॉब बहुत छोटे हैं, तो ओवरहेड की वजह से, असल काम को पूरा करने के बजाय, उसे रोकने और फिर से शुरू करने में ज़्यादा समय लग सकता है.

एक तरीका यह है कि टास्क का बैच बनाया जाए. अगर पिछले टास्क को पूरा हुए काफ़ी समय हो गया है, तो ही उनके बीच में रुकावट डालें. आम तौर पर, टास्क को ज़्यादा समय लेने वाले टास्क बनने से रोकने के लिए, 50 मिलीसेकंड की समयसीमा तय की जाती है. हालांकि, रिस्पॉन्सिवनेस और जॉब सूची को पूरा करने में लगने वाले समय के बीच संतुलन बनाने के लिए, इसमें बदलाव किया जा सकता है.

async function runJobs(jobQueue, deadline=50) {
  let lastYield = performance.now();

  for (const job of jobQueue) {
    // Run the job:
    job();

    // If it's been longer than the deadline, yield to the main thread:
    if (performance.now() - lastYield > deadline) {
      await yieldToMain();
      lastYield = performance.now();
    }
  }
}

इससे टास्क छोटे-छोटे हिस्सों में बंट जाते हैं, ताकि उन्हें पूरा होने में ज़्यादा समय न लगे. हालांकि, रनर हर 50 मिलीसेकंड में मुख्य थ्रेड को कंट्रोल देता है.

Chrome DevTools के परफ़ॉर्मेंस पैनल में दिखने वाले जॉब फ़ंक्शन की एक सीरीज़, जिसमें उनके एक्ज़ीक्यूशन को कई टास्क में बांटा गया है
जॉब को कई टास्क में बांटा गया है.

isInputPending() का इस्तेमाल न करें

Browser Support

  • Chrome: 87.
  • Edge: 87.
  • Firefox: not supported.
  • Safari: not supported.

Source

isInputPending() एपीआई से यह पता लगाया जा सकता है कि किसी उपयोगकर्ता ने पेज से इंटरैक्ट करने की कोशिश की है या नहीं. साथ ही, यह सिर्फ़ तब यील्ड करता है, जब कोई इनपुट पेंडिंग हो.

इससे JavaScript को टास्क की सूची के आखिर में जाने के बजाय, अपना काम जारी रखने में मदद मिलती है. इससे परफ़ॉर्मेंस में काफ़ी सुधार हो सकता है. इसके बारे में Intent to Ship में बताया गया है. यह उन साइटों के लिए है जो मुख्य थ्रेड पर वापस नहीं आ सकतीं.

हालांकि, उस एपीआई के लॉन्च होने के बाद से, यील्डिंग के बारे में हमारी समझ बढ़ी है. खास तौर पर, आईएनपी के लॉन्च होने के बाद. हम इस एपीआई का इस्तेमाल करने का सुझाव नहीं देते. इसके बजाय, हमारा सुझाव है कि आप इनपुट बाकी है या नहीं, इस बात की परवाह किए बिना, कई वजहों से यील्ड करें:

  • कुछ मामलों में, उपयोगकर्ता के इंटरैक्ट करने के बावजूद, isInputPending() गलत तरीके से false दिखा सकता है.
  • इनपुट ही ऐसा मामला नहीं है जहां टास्क को यील्ड करना चाहिए. किसी वेब पेज को रिस्पॉन्सिव बनाने के लिए, ऐनिमेशन और यूज़र इंटरफ़ेस के अन्य अपडेट भी उतने ही ज़रूरी हो सकते हैं.
  • इसके बाद, ज़्यादा बेहतर यील्डिंग एपीआई लॉन्च किए गए. इनसे यील्डिंग से जुड़ी समस्याएं हल की जा सकती हैं. जैसे, scheduler.postTask() और scheduler.yield().

नतीजा

टास्क मैनेज करना मुश्किल है. हालांकि, ऐसा करने से यह पक्का होता है कि आपका पेज, उपयोगकर्ता के इंटरैक्शन का जवाब ज़्यादा तेज़ी से दे. टास्क को मैनेज करने और उन्हें प्राथमिकता देने के लिए, कोई एक सलाह नहीं दी जा सकती. इसके लिए, कई अलग-अलग तकनीकें अपनाई जा सकती हैं. टास्क मैनेज करते समय, इन मुख्य बातों का ध्यान रखें:

  • उपयोगकर्ता के लिए ज़रूरी टास्क के लिए, मुख्य थ्रेड को प्राथमिकता दें.
  • scheduler.yield() का इस्तेमाल करें (क्रॉस-ब्राउज़र फ़ॉलबैक के साथ), ताकि आसानी से काम किया जा सके और प्राथमिकता के हिसाब से काम जारी रखा जा सके
  • आखिर में, अपने फ़ंक्शन में कम से कम काम करें.

scheduler.yield(), इसके टास्क-शेड्यूलिंग रिलेटिव scheduler.postTask(), और टास्क को प्राथमिकता देने के बारे में ज़्यादा जानने के लिए, Prioritized Task Scheduling API के दस्तावेज़ देखें.

इनमें से एक या उससे ज़्यादा टूल की मदद से, अपने ऐप्लिकेशन में काम को इस तरह से स्ट्रक्चर किया जा सकता है कि उपयोगकर्ता की ज़रूरतों को प्राथमिकता दी जाए. साथ ही, यह भी पक्का किया जा सके कि कम ज़रूरी काम भी पूरे हो जाएं. इससे उपयोगकर्ताओं को बेहतर अनुभव मिलेगा. साथ ही, उन्हें ज़्यादा रिस्पॉन्सिव और मज़ेदार अनुभव मिलेगा.

इस गाइड की तकनीकी जांच करने के लिए, फ़िलिप वॉल्टन को खास तौर पर धन्यवाद.