शेड्यूलr.yield ऑरिजिन ट्रायल पेश है

उपयोगकर्ता के इनपुट का तुरंत जवाब देने वाली वेबसाइटें बनाना, वेब परफ़ॉर्मेंस के सबसे चुनौती भरे पहलुओं में से एक रहा है—यह कि Chrome टीम, वेब डेवलपर को पूरा करने में मदद करने के लिए कड़ी मेहनत कर रही है. ठीक इसी साल, यह एलान किया गया था कि इंटरैक्शन टू नेक्स्ट पेंट (आईएनपी) मेट्रिक को एक्सपेरिमेंटल स्टेटस से 'मंज़ूरी बाकी है' स्टेटस में बदल दिया जाएगा. मार्च 2024 में, फ़र्स्ट इनपुट डिले (एफ़आईडी) को वेबसाइट की परफ़ॉर्मेंस की अहम जानकारी देने वाली मेट्रिक के तौर पर बदल दिया जाएगा.

नए एपीआई डिलीवर करने के लिए लगातार कोशिश की जा रही है, ताकि वेब डेवलपर अपनी वेबसाइटों को जितना हो सके उतना आसान बना सकें. इसके लिए, Chrome टीम फ़िलहाल Chrome के 115 वर्शन से, scheduler.yield के लिए ऑरिजिन ट्रायल चला रही है. शेड्यूलर एपीआई में scheduler.yield एक नया जोड़ा गया है. इसकी मदद से, मुख्य थ्रेड पर कंट्रोल वापस पाने का आसान और बेहतर तरीका, आम तौर पर इस्तेमाल किए जाने वाले तरीकों के मुकाबले बेहतर है.

मिलने पर

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

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

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

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

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

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

फ़ायदा पाने की मौजूदा रणनीतियों से जुड़ी समस्या

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

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

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

  1. टास्क को समय-समय पर चलाएं लेबल वाले सबसे ऊपर मौजूद बटन पर क्लिक करें. यह ब्लॉक करने वाले टास्क को बार-बार चलाने के लिए शेड्यूल करेगा. इस बटन पर क्लिक करने पर, टास्क लॉग में कई मैसेज दिखेंगे. इनमें setInterval का इस्तेमाल करके टास्क को ब्लॉक करना लिखा होगा.
  2. इसके बाद, रन लूप, हर इटरेशन पर setTimeout के साथ मिल रहा है लेबल वाले बटन पर क्लिक करें.

आपको डेमो के नीचे मौजूद बॉक्स में कुछ ऐसा दिखेगा:

Processing loop item 1
Processing loop item 2
Ran blocking task via setInterval
Processing loop item 3
Ran blocking task via setInterval
Processing loop item 4
Ran blocking task via setInterval
Processing loop item 5
Ran blocking task via setInterval
Ran blocking task via setInterval

यह आउटपुट, "टास्क की सूची में मौजूद आखिरी पेज" के तरीके के बारे में बताता है. यह तरीका तब दिखता है, जब setTimeout के साथ काम किया जाता है. लूप में, पांच आइटम प्रोसेस किए जाते हैं. हर आइटम प्रोसेस होने के बाद, setTimeout मिलता है.

यह वेब की एक आम समस्या दिखाता है: स्क्रिप्ट—खास तौर पर किसी तीसरे पक्ष की स्क्रिप्ट—का टाइमर फ़ंक्शन, जो कुछ समय के अंतराल पर काम करता रहता है, को रजिस्टर करना असामान्य नहीं है. setTimeout के साथ मिलने वाली "टास्क सूची का अंत" व्यवहार का मतलब है कि नतीजे देने के बाद लूप को जो काम करना है उससे पहले, टास्क के अन्य सोर्स का काम सूची में शामिल हो सकता है.

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

scheduler.yield में जाएं

Chrome के वर्शन 115 से, scheduler.yield एक एक्सपेरिमेंटल वेब प्लैटफ़ॉर्म सुविधा के रूप में उपलब्ध है. आपके पास एक सवाल यह हो सकता है कि "जब setTimeout पहले से ही ऐसा कर रहा है, तो मुझे खास फ़ंक्शन की ज़रूरत क्यों है?"

यह ध्यान देने वाली बात है कि यील्डिंग का लक्ष्य setTimeout का डिज़ाइन लक्ष्य नहीं था, बल्कि बाद में बाद में किसी कॉलबैक को चलाने के लिए उसे शेड्यूल करने का एक अच्छा खराब असर था—भले ही टाइम आउट वैल्यू 0 दी गई हो. हालांकि, यह याद रखना अहम है कि setTimeout के साथ होने वाले काम को, टास्क सूची के पिछले सेक्शन में भेजा जाता है. डिफ़ॉल्ट रूप से, scheduler.yield बाकी काम को सूची के सामने हिस्से में भेज देता है. इसका मतलब है कि आपको जो काम, नतीजे मिलने के तुरंत बाद फिर से शुरू करना है वह अन्य सोर्स से अब भी काम नहीं करेगा. हालांकि, उपयोगकर्ता इंटरैक्शन के मामले में कोई अपवाद नहीं है.

scheduler.yield एक ऐसा फ़ंक्शन है जो मुख्य थ्रेड में जनरेट होता है और कॉल करने पर Promise दिखाता है. इसका मतलब है कि इसे async फ़ंक्शन में await किया जा सकता है:

async function yieldy () {
  // Do some work...
  // ...

  // Yield!
  await scheduler.yield();

  // Do some more work...
  // ...
}

scheduler.yield को काम करता हुआ देखने के लिए, ये काम करें:

  1. chrome://flags पर नेविगेट करें.
  2. एक्सपेरिमेंट के तौर पर उपलब्ध वेब प्लैटफ़ॉर्म की सुविधाएं एक्सपेरिमेंट चालू करें. ऐसा करने के बाद, आपको Chrome को रीस्टार्ट करना पड़ सकता है.
  3. डेमो पेज पर जाएं या इस सूची के नीचे एम्बेड किए गए वर्शन का इस्तेमाल करें.
  4. समय-समय पर टास्क चलाएं लेबल वाले सबसे ऊपर मौजूद बटन पर क्लिक करें.
  5. आखिर में, रन लूप, हर इटरेशन पर scheduler.yield के साथ मिलता है लेबल वाले बटन पर क्लिक करें.

पेज के नीचे बॉक्स में आउटपुट कुछ ऐसा दिखेगा:

Processing loop item 1
Processing loop item 2
Processing loop item 3
Processing loop item 4
Processing loop item 5
Ran blocking task via setInterval
Ran blocking task via setInterval
Ran blocking task via setInterval
Ran blocking task via setInterval
Ran blocking task via setInterval

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

इसे आज़माएं!

अगर scheduler.yield आपको पसंद आ रहा है और आपको इसे आज़माना है, तो Chrome के वर्शन 115 से इसे दो तरीकों से आज़माया जा सकता है:

  1. अगर आपको स्थानीय तौर पर scheduler.yield का इस्तेमाल करना है, तो Chrome के पता बार में chrome://flags टाइप करें और डालें. इसके बाद, प्रयोग के तौर पर उपलब्ध वेब प्लैटफ़ॉर्म की सुविधाएं सेक्शन के ड्रॉपडाउन से चालू करें चुनें. इससे scheduler.yield (और परफ़ॉर्मेंस से जुड़ी अन्य सुविधाएं) सिर्फ़ आपके Chrome के इंस्टेंस में उपलब्ध होगी.
  2. अगर आपको scheduler.yield को सार्वजनिक तौर पर ऐक्सेस किए जा सकने वाले ऑरिजिन पर, Chromium के असल उपयोगकर्ताओं के लिए चालू करना है, तो आपको scheduler.yield ऑरिजिन ट्रायल के लिए साइन अप करना होगा. ऐसा करने से, किसी तय समयावधि के लिए, सुझाई गई सुविधाओं के साथ सुरक्षित तरीके से एक्सपेरिमेंट किया जा सकता है. साथ ही, Chrome की टीम को इस बात की अहम जानकारी मिलती है कि फ़ील्ड में उन सुविधाओं का इस्तेमाल कैसे किया जाता है. ऑरिजिन ट्रायल के काम करने के तरीके के बारे में ज़्यादा जानने के लिए, यह गाइड पढ़ें.

आपके लक्ष्य क्या हैं, यह इस बात पर निर्भर करता है कि scheduler.yield को कैसे इस्तेमाल किया जाता है. हालांकि, ऐसे ब्राउज़र जो इसे लागू नहीं करते, उनके साथ भी काम करता रहेगा. आधिकारिक पॉलीफ़िल का इस्तेमाल किया जा सकता है. पॉलीफ़िल तब काम आता है, जब आपकी स्थिति में नीचे दी गई बातें लागू होती हैं:

  1. आपके ऐप्लिकेशन में, टास्क शेड्यूल करने के लिए, पहले से ही scheduler.postTask का इस्तेमाल किया जा रहा है.
  2. आप टास्क और काम की प्राथमिकताएं सेट करना चाहते हों.
  3. आपको scheduler.postTask एपीआई की ओर से दी जाने वाली TaskController क्लास से, टास्क रद्द करना हो या उनकी संख्या बदलनी हो.

अगर यह आपकी स्थिति नहीं बताती, तो शायद पॉलीफ़िल आपके काम का न हो. ऐसे मामले में, आप कई तरीकों से अपना फ़ॉलबैक रोल कर सकते हैं. पहले तरीके में, scheduler.yield के उपलब्ध होने पर इसका इस्तेमाल किया जाता है. हालांकि, अगर यह उपलब्ध नहीं है, तो यह setTimeout पर वापस चला जाता है:

// A function for shimming scheduler.yield and setTimeout:
function yieldToMain () {
  // Use scheduler.yield if it exists:
  if ('scheduler' in window && 'yield' in scheduler) {
    return scheduler.yield();
  }

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

// Example usage:
async function doWork () {
  // Do some work:
  // ...

  await yieldToMain();

  // Do some other work:
  // ...
}

यह काम कर सकता है, लेकिन जैसा कि आप अनुमान लगा सकते हैं, जो ब्राउज़र scheduler.yield का समर्थन नहीं करते, वे "सूची में आगे" व्यवहार के बिना भी काम करेंगे. अगर इसका मतलब है कि आपको बिलकुल नहीं मिलेगा, तो कोई दूसरा तरीका आज़माएं. इसमें, scheduler.yield के उपलब्ध होने पर उसका इस्तेमाल किया जाता है. हालांकि, उपलब्ध न होने पर आपको कोई नतीजे नहीं मिलेंगे:

// A function for shimming scheduler.yield with no fallback:
function yieldToMain () {
  // Use scheduler.yield if it exists:
  if ('scheduler' in window && 'yield' in scheduler) {
    return scheduler.yield();
  }

  // Fall back to nothing:
  return;
}

// Example usage:
async function doWork () {
  // Do some work:
  // ...

  await yieldToMain();

  // Do some other work:
  // ...
}

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

Unsplash की हीरो इमेज, जिसे जोनाथन ऐलिसन ने बनाया है.