पेज लाइफ़साइकल एपीआई

ब्राउज़र सहायता

  • 68
  • 79
  • x
  • x

आज-कल के मॉडर्न ब्राउज़र कभी-कभी पेजों को निलंबित कर देते हैं या सिस्टम के रिसॉर्स सीमित होने पर, उन्हें पूरी तरह से खारिज कर देते हैं. आने वाले समय में, ब्राउज़र ऐसा करना चाहते हैं, ताकि वे कम पावर और मेमोरी का इस्तेमाल करें. Page Lifecycle API से लाइफ़साइकल हुक मिलते हैं, ताकि आपके पेज उपयोगकर्ता अनुभव पर असर डाले बिना, ब्राउज़र की इन गतिविधियों को सुरक्षित तरीके से मैनेज कर सकें. एपीआई पर एक नज़र डालें और देखें कि आपको अपने ऐप्लिकेशन में इन सुविधाओं को लागू करना चाहिए या नहीं.

बैकग्राउंड

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

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

वेब प्लैटफ़ॉर्म पर लंबे समय से ऐसे इवेंट मौजूद हैं जो लाइफ़साइकल की स्थितियों से जुड़े रहते हैं, जैसे कि load, unload, और visibilitychange — ये इवेंट सिर्फ़ डेवलपर को उपयोगकर्ता की शुरू की गई लाइफ़साइकल की स्थिति में हुए बदलावों के हिसाब से जवाब देने की अनुमति देते हैं. वेब के लिए कम क्षमता वाले डिवाइस पर सही तरीके से काम करने के लिए (और सभी प्लैटफ़ॉर्म पर अपनी संसाधनों को बेहतर तरीके से इस्तेमाल करना) के लिए, ब्राउज़र को सिस्टम के संसाधनों पर अपने-आप फिर से दावा करने और उन्हें फिर से असाइन करने के तरीके की ज़रूरत होती है.

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

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

Page Lifecycle API इस समस्या को हल करने की कोशिश करता है:

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

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

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

पेज लाइफ़साइकल की स्थितियों और इवेंट की खास जानकारी

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

पेज लाइफ़साइकल की स्थितियों और उनके बीच ट्रांज़िशन का सिग्नल देने वाले इवेंट को समझाने का सबसे आसान तरीका, डायग्राम की मदद से है:

इस दस्तावेज़ में, स्थिति और इवेंट के फ़्लो को विज़ुअल तौर पर दिखाया गया है.
Page Lifecycle API की स्थिति और इवेंट फ़्लो.

राज्य

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

स्थिति ब्यौरा
चालू

अगर कोई पेज दिख रहा है और उसमें इनपुट फ़ोकस मौजूद है, तो वह चालू स्थिति में होता है.

संभावित पिछली स्थितियां:
काम नहीं कर रहे (focus इवेंट के ज़रिए)
फ़्रीज़ (resume इवेंट के ज़रिए, फिर pageshow इवेंट के ज़रिए)

अगली स्थिति:
पैसिव ( blur इवेंट के ज़रिए)

पैसिव

अगर पेज दिख रहा है और उसमें इनपुट फ़ोकस मौजूद नहीं है, तो यह बंद स्थिति में होता है.

संभावित पिछली स्थितियां:
चालू (blur इवेंट के ज़रिए)
छिपाया गया ( visibilitychange इवेंट के ज़रिए)
बंद (resume इवेंट के ज़रिए, pageshow

अगली स्थिति:
चालू है (focus इवेंट के ज़रिए)
छिपाया गया ( visibilitychange इवेंट के ज़रिए)

छिपा हुआ

अगर कोई पेज नहीं दिखता है, तो यह छिपा हुआ स्थिति में होता है. साथ ही, पेज को फ़्रीज़, खारिज या खत्म न किया गया हो.

संभावित पिछली स्थितियां:
काम नहीं कर रहे ( visibilitychange इवेंट के ज़रिए)
फ़्रीज़ (resume इवेंट के ज़रिए, फिर pageshow इवेंट के ज़रिए)

आगे की संभावित स्थितियां:
काम नहीं कर रहे ( visibilitychange इवेंट के ज़रिए)
फ़्रीज़ (freeze इवेंट के ज़रिए)
अस्वीकार किए गए (कोई इवेंट ट्रिगर नहीं हुआ)
बंद (कोई इवेंट चालू नहीं)

फ़्रोज़न

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

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

संभावित पिछली स्थितियां:
छिपाया गया (freeze इवेंट के ज़रिए)

आगे की संभावित स्थितियां:
चालू (resume इवेंट के ज़रिए, फिर pageshow इवेंट के ज़रिए)
पैसिव pageshowpageshowइवेंट pageshowpageshow19}19}19 आइटम का मैसेज19} हो गया है


resume

बंद किया गया

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

संभावित पिछली स्थितियां:
छिपाया गया (pagehide इवेंट के ज़रिए)

अगली स्थिति:
कुछ नहीं

खारिज किया गया

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

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

संभावित पिछली स्थितियां:
छिपाया गया (कोई इवेंट ट्रिगर नहीं किया गया)
फ़्रीज़ किया गया (कोई इवेंट ट्रिगर नहीं किया गया)

अगली स्थिति:
कुछ नहीं

इवेंट

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

नाम ब्यौरा
focus

किसी DOM एलिमेंट पर फ़ोकस किया गया है.

ध्यान दें: focus इवेंट का मतलब ज़रूरी नहीं है कि इवेंट की स्थिति में बदलाव हो. इससे स्थिति में बदलाव का संकेत सिर्फ़ तब मिलता है, जब पेज पर पहले से इनपुट फ़ोकस मौजूद नहीं था.

संभावित पिछली स्थितियां:
पैसिव

मौजूदा स्थितियां:
चालू है

blur

डीओएम एलिमेंट ने फ़ोकस खो दिया है.

ध्यान दें: blur इवेंट का मतलब ज़रूरी नहीं है कि इवेंट की स्थिति में बदलाव हो. यह स्थिति में बदलाव का संकेत सिर्फ़ तब देता है, जब पेज में इनपुट फ़ोकस मौजूद नहीं होता है. इसका मतलब है कि पेज ने सिर्फ़ फ़ोकस को एक एलिमेंट से दूसरे एलिमेंट पर स्विच नहीं किया है.

संभावित पिछली स्थितियां:
चालू है

मौजूदा स्थितियां:
पैसिव

visibilitychange

दस्तावेज़ की visibilityState वैल्यू बदल गई है. ऐसा तब हो सकता है, जब उपयोगकर्ता किसी नए पेज पर जाता है, टैब स्विच करता है, किसी टैब को बंद करता है, ब्राउज़र को छोटा या बंद करता है या मोबाइल ऑपरेटिंग सिस्टम पर ऐप्लिकेशन स्विच करता है.

संभावित पिछली स्थितियां:
पैसिव
छिपाया गया

संभावित मौजूदा स्थितियां:
पैसिव
छिपाया गया

freeze *

पेज को अभी-अभी फ़्रीज़ किया गया है. पेज की टास्क सूची में, फ़्रीज़ किया जा सकने वाला टास्क शुरू नहीं होगा.

संभावित पिछली स्थितियां:
छिपाया गया

मौजूदा स्थितियां:
बंद की गई

resume *

ब्राउज़र ने फ़्रीज़ किया हुआ पेज फिर से शुरू कर दिया है.

संभावित पिछली स्थितियां:
फ़्रोज़न की गई

संभावित मौजूदा स्थितियां:
चालू है (अगर इसके बाद pageshow इवेंट आता है)
पैसिव (अगर इसके बाद pageshow इवेंट आता है)
छिपाया गया

pageshow

सेशन के इतिहास की एंट्री का पता लगाया जा रहा है.

यह नया पेज लोड हो सकता है या बैक/फ़ॉरवर्ड कैश मेमोरी से लिया गया कोई पेज हो सकता है. अगर पेज को बैक-फ़ॉरवर्ड कैश मेमोरी से लिया गया है, तो इवेंट की persisted प्रॉपर्टी true होगी. ऐसा न होने पर, यह false प्रॉपर्टी होगी.

संभावित पिछली स्थितियां:
बंद (किसी resume इवेंट को भी ट्रिगर कर दिया गया होगा)

संभावित मौजूदा स्थितियां:
चालू है
बंद
छिपाया गया

pagehide

सेशन के इतिहास की एंट्री का पता लगाया जा रहा है.

अगर उपयोगकर्ता किसी दूसरे पेज पर जा रहा है और ब्राउज़र मौजूदा पेज को बाद में इस्तेमाल करने के लिए, बैक/फ़ॉरवर्ड कैश मेमोरी में जोड़ पा रहा है, तो इवेंट की persisted प्रॉपर्टी true होगी. जब true, पेज फ़्रीज़ स्थिति में होता है, तो यह बंद की गई स्थिति में होता है.

संभावित पिछली स्थितियां:
छिपाया गया

संभावित मौजूदा स्थितियां:
कुछ समय के लिए रोक दी गई है (event.persisted सही है, freeze इवेंट का पालन किया जा रहा है)
रद्द किया गया (event.persisted गलत है, unload इवेंट इस तरह का है)

beforeunload

विंडो, दस्तावेज़, और उसके संसाधन अनलोड होने वाले हैं. दस्तावेज़ अब भी दिख रहा है और इस समय इवेंट को रद्द किया जा सकता है.

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

संभावित पिछली स्थितियां:
छिपाया गया

मौजूदा स्थितियां:
बंद की गई

unload

पेज अनलोड किया जा रहा है.

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

संभावित पिछली स्थितियां:
छिपाया गया

संभावित मौजूदा स्थितियां:
बंद

* से उस नए इवेंट के बारे में पता चलता है जिसे Page Lifecycle API ने तय किया है

Chrome 68 में जोड़ी गई नई सुविधाएं

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

डेवलपर अब Chrome 68 में, document पर होने वाले freeze और resume इवेंट सुनकर देख सकते हैं कि छिपा हुआ टैब कब फ़्रीज़ हुआ और रुका हुआ है.

document.addEventListener('freeze', (event) => {
  // The page is now frozen.
});

document.addEventListener('resume', (event) => {
  // The page has been unfrozen.
});

Chrome 68 से document ऑब्जेक्ट में, अब डेस्कटॉप Chrome पर एक wasDiscarded प्रॉपर्टी शामिल है (इस समस्या में, Android सहायता को ट्रैक किया जा रहा है). यह पता लगाने के लिए कि छिपे हुए टैब में पेज को खारिज किया गया है या नहीं, पेज लोड होने के दौरान इस प्रॉपर्टी की वैल्यू की जांच की जा सकती है. ध्यान दें: जिन पेजों को फिर से इस्तेमाल करने के लिए खारिज किया गया है उन्हें फिर से लोड करना ज़रूरी है.

if (document.wasDiscarded) {
  // Page was previously discarded by the browser while in a hidden tab.
}

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

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

कोड में पेज की लाइफ़साइकल स्थितियों को देखने का तरीका

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

const getState = () => {
  if (document.visibilityState === 'hidden') {
    return 'hidden';
  }
  if (document.hasFocus()) {
    return 'active';
  }
  return 'passive';
};

फ़्रीज़ हुई और बंद की गई स्थितियों का पता, इवेंट लिसनर (freeze और pagehide) में ही रिकॉर्ड किया जा सकता है, क्योंकि इवेंट की स्थिति बदलती रहती है.

स्थिति में हुए बदलावों पर नज़र रखने का तरीका

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

// Stores the initial state using the `getState()` function (defined above).
let state = getState();

// Accepts a next state and, if there's been a state change, logs the
// change to the console. It also updates the `state` value defined above.
const logStateChange = (nextState) => {
  const prevState = state;
  if (nextState !== prevState) {
    console.log(`State change: ${prevState} >>> ${nextState}`);
    state = nextState;
  }
};

// Options used for all event listeners.
const opts = {capture: true};

// These lifecycle events can all use the same listener to observe state
// changes (they call the `getState()` function to determine the next state).
['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'].forEach((type) => {
  window.addEventListener(type, () => logStateChange(getState(), opts));
});

// The next two listeners, on the other hand, can determine the next
// state from the event itself.
window.addEventListener('freeze', () => {
  // In the freeze event, the next state is always frozen.
  logStateChange('frozen');
}, opts);

window.addEventListener('pagehide', (event) => {
  // If the event's persisted property is `true` the page is about
  // to enter the back/forward cache, which is also in the frozen state.
  // If the event's persisted property is not `true` the page is
  // about to be unloaded.
  logStateChange(event.persisted ? 'frozen' : 'terminated');
}, opts);

यह कोड तीन काम करता है:

  • getState() फ़ंक्शन का इस्तेमाल करके शुरुआती स्थिति सेट करता है.
  • यह एक ऐसा फ़ंक्शन तय करता है जो अगली स्थिति स्वीकार करता है. कोई बदलाव होने पर, स्थिति के बदलावों को कंसोल में लॉग करता है.
  • यह लाइफ़साइकल के सभी ज़रूरी इवेंट के लिए, इवेंट लिसनर को कैप्चर करता है, जो अगली स्थिति में logStateChange() को पास हो जाता है.

कोड के बारे में ध्यान देने वाली बात यह है कि इवेंट को सुनने वाले सभी लोगों को window में जोड़ा जाता है और वे सभी {capture: true} को पास कर लेते हैं. ऐसा होने की कुछ वजहें होती हैं. जैसे:

  • सभी पेज लाइफ़साइकल इवेंट का टारगेट एक जैसा नहीं होता. pagehide और pageshow, window को ट्रिगर होते हैं. visibilitychange, freeze, और resume, document को ट्रिगर होते हैं. साथ ही, focus और blur, अपने-अपने डीओएम एलिमेंट पर ट्रिगर होते हैं.
  • इनमें से ज़्यादातर इवेंट बबल नहीं होते हैं. इसका मतलब है कि कैप्चर नहीं किए जाने वाले इवेंट लिसनर को किसी एक पूर्व एलिमेंट में जोड़ा जा सकता है और सभी को ट्रैक नहीं किया जा सकता.
  • कैप्चर करने का फ़ेज़, टारगेट या बबल फ़ेज़ से पहले काम करता है. इसलिए, लोगों को वहां जोड़ने से, यह पक्का करने में मदद मिलती है कि किसी दूसरे कोड के रद्द होने से पहले ही वे चले जाएं.

हर राज्य के लिए डेवलपर के सुझाव

डेवलपर के तौर पर, पेज लाइफ़साइकल की स्थितियों को समझना ज़रूरी है और उन्हें कोड में देखने का तरीका जानना भी ज़रूरी है. ऐसा इसलिए, क्योंकि आपको किस तरह का काम करना चाहिए (और नहीं करना चाहिए), यह काफ़ी हद तक इस बात पर निर्भर करता है कि आपका पेज किस स्थिति में है.

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

स्थिति डेवलपर के लिए सुझाव
Active

उपयोगकर्ता के लिए चालू स्थिति सबसे अहम समय होती है और इस वजह से आपके पेज के लिए उपयोगकर्ता के इनपुट के हिसाब से सबसे ज़रूरी समय आ जाना चाहिए.

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

Passive

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

जब पेज चालू से पैसिव में बदल जाता है, तो ऐप्लिकेशन की सेव नहीं की गई स्थिति को बनाए रखने का सही समय है.

Hidden

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

छिपा हुआ पेज भी वह आखिरी बदलाव होता है जिसकी निगरानी डेवलपर आसानी से कर सकते हैं. यह खास तौर पर मोबाइल पर होता है, क्योंकि उपयोगकर्ता खुद टैब या ब्राउज़र ऐप्लिकेशन को बंद कर सकते हैं. ऐसे मामलों में beforeunload, pagehide, और unload इवेंट ट्रिगर नहीं होते हैं.

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

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

Frozen

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

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

खास तौर पर, यह ज़रूरी है कि:

  • सभी खुले IndexedDB कनेक्शन बंद करें.
  • खुले BroadcastChannel कनेक्शन को बंद करें.
  • चालू WebRTC कनेक्शन बंद करें.
  • किसी भी नेटवर्क पोलिंग को रोकें या किसी भी खुले वेब सॉकेट कनेक्शन को बंद करें.
  • होल्ड किए गए किसी भी Web Lock को रिलीज़ करें.

अगर पेज को खारिज करके बाद में फिर से लोड किया जाता है, तो आपको उस डाइनैमिक व्यू स्थिति (जैसे कि अनंत सूची वाले व्यू में स्क्रोल की पोज़िशन) को sessionStorage (या IndexedDB के ज़रिए commit()) तक भी बनाए रखना चाहिए.

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

Terminated

आम तौर पर, किसी पेज के बंद किए गए वर्शन पर ट्रांज़िशन होने पर, आपको कुछ भी करने की ज़रूरत नहीं होती.

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

साथ ही, जैसा कि छिपे हुए स्टेटस के लिए सुझावों में बताया गया है, डेवलपर के लिए यह समझना बहुत ज़रूरी है कि बंद की गई स्थिति पर ट्रांज़िशन का कई मामलों (खास तौर पर मोबाइल पर) पर सही तरीके से पता नहीं लगाया जा सकता. इसलिए, हो सकता है कि वे डेवलपर डेटा खो दें जो सदस्यता खत्म करने के इवेंट (उदाहरण के लिए, beforeunload, pagehide, और unload) पर निर्भर रहते हैं.

Discarded

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

इस वजह से, आपको बदलाव को छिपाए गए से फ़्रीज़ किए जाने की संभावना के लिए तैयार करना होगा. इसके बाद, document.wasDiscarded पर सही का निशान लगाकर, पेज लोड होने के दौरान खारिज किए गए पेज को पहले जैसा करने की कार्रवाई की जा सकती है.

एक बार फिर बता दें कि सभी ब्राउज़र में लाइफ़साइकल इवेंट की विश्वसनीयता और उनका क्रम एक जैसा नहीं है. इसलिए, टेबल में दी गई सलाह को अपनाने का सबसे आसान तरीका PageLifecycle.js का इस्तेमाल करना है.

बचने के लिए, लेगसी लाइफ़साइकल एपीआई

जहां भी संभव हो, इन इवेंट से बचना चाहिए.

अनलोड इवेंट

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

इस वजह से, सेशन कब खत्म होता है, यह तय करने के लिए visibilitychange इवेंट पर भरोसा करना हमेशा बेहतर होता है. साथ ही, छिपी हुई स्थिति को ऐप्लिकेशन और उपयोगकर्ता के डेटा को सेव करने का आखिरी समय के तौर पर देखना बेहतर होता है.

इसके अलावा, रजिस्टर किए गए unload इवेंट हैंडलर (onunload या addEventListener() के ज़रिए) की मौजूदगी से ब्राउज़र, पेजों को बैक/फ़ॉरवर्ड कैश मेमोरी में नहीं रख सकते, ताकि वे तेज़ी से बैक और फ़ॉरवर्ड लोड हो सकें.

सभी मॉडर्न ब्राउज़र में, हमारा सुझाव है कि आप हमेशा पेज के अनलोड होने का पता लगाने के लिए, unload इवेंट के बजाय pagehide इवेंट का इस्तेमाल करें. इसे खत्म किया गया स्टेटस भी कहा जाता है. अगर आपको Internet Explorer के वर्शन 10 और इससे पहले के वर्शन पर काम करना चाहिए, तो आपको pagehide इवेंट का पता लगाने की सुविधा देनी चाहिए. साथ ही, unload का इस्तेमाल सिर्फ़ तब करना चाहिए, जब ब्राउज़र pagehide पर काम न करता हो:

const terminationEvent = 'onpagehide' in self ? 'pagehide' : 'unload';

window.addEventListener(terminationEvent, (event) => {
  // Note: if the browser is able to cache the page, `event.persisted`
  // is `true`, and the state is frozen rather than terminated.
});

beforeunload इवेंट

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

beforeunload और unload के बीच एक अंतर यह है कि beforeunload का कानूनी तौर पर इस्तेमाल किया जाता है. उदाहरण के लिए, जब उपयोगकर्ता को चेतावनी देनी हो कि उनके बदलाव सेव नहीं किए गए हैं, तो पेज को अनलोड करना जारी रखने पर वे बदलाव नहीं कर पाएंगे.

beforeunload को इस्तेमाल करने की सही वजहें हैं, इसलिए हमारा सुझाव है कि आप सिर्फ़ तब beforeunload लिसनर को जोड़ें, जब उपयोगकर्ता के पास सेव नहीं किए गए बदलाव हों. इसके बाद, उन्हें सेव करने के तुरंत बाद हटा दें.

दूसरे शब्दों में, ऐसा न करें (क्योंकि यह बिना किसी शर्त के, beforeunload लिसनर को जोड़ता है):

addEventListener('beforeunload', (event) => {
  // A function that returns `true` if the page has unsaved changes.
  if (pageHasUnsavedChanges()) {
    event.preventDefault();

    // Legacy support for older browsers.
    return (event.returnValue = true);
  }
});

इसके बजाय, ऐसा करें (क्योंकि ज़रूरत पड़ने पर ही यह beforeunload लिसनर को जोड़ता है और ऐसा न होने पर इसे हटा देता है):

const beforeUnloadListener = (event) => {
  event.preventDefault();
  
  // Legacy support for older browsers.
  return (event.returnValue = true);
};

// A function that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges(() => {
  addEventListener('beforeunload', beforeUnloadListener);
});

// A function that invokes a callback when the page's unsaved changes are resolved.
onAllChangesSaved(() => {
  removeEventListener('beforeunload', beforeUnloadListener);
});

अक्सर पूछे जाने वाले सवाल

"लोड हो रहा है" स्थिति क्यों नहीं दिख रही है?

Page Lifecycle API के मुताबिक स्थितियां अलग-अलग और म्युचुअली एक्सक्लूसिव होती हैं. किसी पेज को ऐक्टिव, पैसिव या छिपे हुए स्टेटस में लोड किया जा सकता है. पेज के लोड होने से पहले उसकी स्थिति बदली जा सकती है या उसे बंद भी किया जा सकता है. इसलिए, इस उदाहरण में पेज लोड होने का कोई मतलब नहीं बनता.

छिपाने पर मेरा पेज ज़रूरी काम करता है, मैं उसे फ़्रीज़ होने या खारिज होने से कैसे रोकूं?

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

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

फ़िलहाल, पेजों को खारिज करते समय Chrome का इस्तेमाल बहुत कम किया जाएगा. ऐसा सिर्फ़ तब किया जा सकेगा, जब उसे पूरा भरोसा हो कि उसका इस्तेमाल करने वालों पर कोई असर नहीं होगा. उदाहरण के लिए, ऐसे पेजों को तब तक खारिज नहीं किया जाएगा, जिनके लिए छिपी हुई स्थिति में, नीचे दिया गया कोई भी काम किया गया हो.

  • ऑडियो चलाया जा रहा है
  • WebRTC का इस्तेमाल करना
  • टेबल का टाइटल या फ़ेविकॉन अपडेट करना
  • सूचनाएं दिखाई जा रही हैं
  • पुश नोटिफ़िकेशन भेजे जा रहे हैं

किसी टैब को सुरक्षित तरीके से फ़्रीज़ या खारिज किया जा सकता है या नहीं, यह तय करने के लिए इस्तेमाल की जाने वाली मौजूदा सुविधाओं की सूची के लिए, यह देखें: Chrome में फ़्रीज़िंग और खारिज करने के तरीके.

बैक/फ़ॉरवर्ड कैश मेमोरी क्या है?

बैक/फ़ॉरवर्ड कैश मेमोरी का इस्तेमाल, नेविगेशन ऑप्टिमाइज़ेशन के लिए किया जाता है. कुछ ब्राउज़र इस सुविधा को लागू करते समय, 'वापस जाएं' और 'आगे बढ़ें' बटन को ज़्यादा तेज़ी से इस्तेमाल करते हैं.

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

सभी इंटेंट और कामों के लिए, यह फ़्रीज़िंग ठीक उसी तरह काम करती है, जैसे कि फ़्रीज़िंग ब्राउज़र, सीपीयू/बैटरी बचाने के लिए काम करते हैं. इस वजह से, इसे फ़्रीज़ लाइफ़साइकल स्थिति का हिस्सा माना जाता है.

अगर मैं फ़्रीज़ किए गए या खत्म हो चुके स्टेटस में एसिंक्रोनस एपीआई नहीं चला सकता, तो मैं IndexedDB में डेटा कैसे सेव करूं?

फ़्रीज़ और बंद किए गए स्टेटस में, पेज की टास्क सूची में फ़्रीज़ किए जा सकने वाले टास्क निलंबित कर दिए जाते हैं. इसका मतलब है कि IndexedDB जैसे एसिंक्रोनस और कॉलबैक-आधारित एपीआई सही तरीके से इस्तेमाल नहीं किए जा सकते.

आने वाले समय में, हम IDBTransaction ऑब्जेक्ट में commit() का तरीका जोड़ेंगे. इससे डेवलपर बेहतर तरीके से ऐसे ट्रांज़ैक्शन कर पाएंगे जिन्हें सिर्फ़ राइट-ओनली ट्रांज़ैक्शन के लिए इस्तेमाल किया जा सकता है. इनमें कॉलबैक की ज़रूरत नहीं होती. दूसरे शब्दों में, अगर डेवलपर सिर्फ़ IndexedDB को डेटा लिख रहा है और वह कॉम्प्लेक्स ट्रांज़ैक्शन नहीं कर रहा है जिसमें रीड और राइट शामिल हैं, तो commit() वाला तरीका, टास्क की सूचियों के निलंबित होने से पहले पूरा कर पाएगा (यह मानते हुए कि IndexedDB डेटाबेस पहले से खुला है).

हालांकि, आज के समय में काम करने वाले कोड के लिए, डेवलपर के पास दो विकल्प हैं:

  • सेशन स्टोरेज का इस्तेमाल करें: सेशन स्टोरेज सिंक्रोनस होता है और यह पेज खारिज करने के दौरान बना रहता है.
  • अपने सर्विस वर्कर से IndexedDB का इस्तेमाल करें: पेज को खत्म या खारिज करने के बाद, सर्विस वर्कर,IndexedDB में डेटा सेव कर सकता है. freeze या pagehide इवेंट लिसनर में, postMessage() की मदद से आपके सर्विस वर्कर को डेटा भेजा जा सकता है. सर्विस वर्कर, डेटा सेव करने के काम को संभाल सकता है.

अपने ऐप्लिकेशन को फ़्रीज़ और खारिज की गई स्थितियों में टेस्ट करना

यह जांचने के लिए कि आपका ऐप्लिकेशन, फ़्रीज़ और खारिज की गई स्थितियों में कैसे काम करता है, chrome://discards पर जाकर अपने किसी भी खुले हुए टैब को असल में फ़्रीज़ या खारिज किया जा सकता है.

Chrome ने यूज़र इंटरफ़ेस (यूआई) को खारिज किया
Chrome ने यूज़र इंटरफ़ेस (यूआई) को खारिज किया

इससे यह पक्का किया जा सकता है कि आपका पेज, freeze और resume इवेंट को सही तरीके से हैंडल करता है. साथ ही, खारिज करने के बाद पेज फिर से लोड होने पर document.wasDiscarded फ़्लैग भी ठीक से हैंडल करता है.

खास जानकारी

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

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