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

Browser Support

  • Chrome: 68.
  • Edge: 79.
  • Firefox: not supported.
  • Safari: not supported.

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

बैकग्राउंड

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

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

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

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

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

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

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

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

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

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

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

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

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

राज्य

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

राज्य ब्यौरा
चालू है

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

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

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

पैसिव

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

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

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

छिपा हुआ

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

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

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

फ़्रीज़ किया गया

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

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

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

अगली संभावित स्थितियां:
active (resume इवेंट के बाद, pageshow इवेंट के ज़रिए)
passive (resume इवेंट के बाद, pageshow इवेंट के ज़रिए)
hidden (resume इवेंट के ज़रिए)
discarded (कोई इवेंट फ़ायर नहीं हुआ)

समझौता खत्म किया गया

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

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

अगली संभावित स्थितियां:
कोई नहीं

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

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

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

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

अगली संभावित स्थितियां:
कोई नहीं

इवेंट

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

नाम विवरण
focus

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

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

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

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

blur

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

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

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

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

visibilitychange

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

पिछली स्थितियां:
निष्क्रिय
छिपाया गया

मौजूदा स्थितियां:
निष्क्रिय
छिपा हुआ

freeze *

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

पिछली स्थितियां:
hidden

मौजूदा स्थितियां:
फ़्रीज़ किया गया

resume *

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

पिछली स्थितियां:
फ़्रीज़ किया गया

मौजूदा स्थितियां:
active (if followed by the pageshow event)
passive (if followed by the pageshow event)
hidden

pageshow

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

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

पिछली संभावित स्थितियां:
frozen (a resume event would have also fired)

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

pagehide

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

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

पिछली स्थितियां:
hidden

मौजूदा स्थितियां:
frozen (event.persisted is true, freeze event follows)
terminated (event.persisted is false, unload event follows)

beforeunload

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

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

पिछली स्थितियां:
hidden

मौजूदा स्थितियां:
terminated

unload

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

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

पिछली स्थितियां:
hidden

मौजूदा स्थितियां:
terminated

* यह 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 को उनके DOM एलिमेंट पर ट्रिगर किया जाता है.
  • इनमें से ज़्यादातर इवेंट बब्ल नहीं होते. इसका मतलब है कि किसी सामान्य पूर्वज एलिमेंट में, कैप्चर न करने वाले इवेंट लिसनर नहीं जोड़े जा सकते. साथ ही, उन सभी को मॉनिटर नहीं किया जा सकता.
  • कैप्चर फ़ेज़, टारगेट या बबल फ़ेज़ से पहले लागू होता है. इसलिए, वहां लिसनर जोड़ने से यह पक्का करने में मदद मिलती है कि वे अन्य कोड से रद्द होने से पहले चलें.

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

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

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

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

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

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

Passive

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

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

Hidden

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

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

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

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

Frozen

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

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

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

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

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

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

Terminated

आम तौर पर, जब कोई पेज बंद किया गया स्थिति में बदलता है, तो आपको कोई कार्रवाई करने की ज़रूरत नहीं होती.

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

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

Discarded

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

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

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

लाइफ़साइकल के पुराने एपीआई, जिनका इस्तेमाल नहीं करना चाहिए

जहां तक हो सके, इन इवेंट से बचें.

अनलोड इवेंट

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

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

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

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

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.
    event.returnValue = true;
  }
});

इसके बजाय, यह तरीका अपनाएं. इससे beforeunload लिसनर सिर्फ़ तब जुड़ता है, जब इसकी ज़रूरत होती है. साथ ही, जब इसकी ज़रूरत नहीं होती, तब यह हट जाता है:

const beforeUnloadListener = (event) => {
  event.preventDefault();

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

// A function that adds a `beforeunload` listener if there are unsaved changes.
onPageHasUnsavedChanges(() => {
  addEventListener('beforeunload', beforeUnloadListener);
});

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

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

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

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

मेरा पेज बैकग्राउंड में ज़रूरी काम करता है. इसे फ़्रीज़ या बंद होने से कैसे रोका जा सकता है?

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

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

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

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

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

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

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

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

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

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

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

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

यह पुष्टि करने के लिए कि डेटा सेव हो गया है, पेज को फिर से लोड करना होगा.

फ़्रीज़ किए गए और खारिज किए गए ऐप्लिकेशन की जांच करना

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

Chrome Discards UI
Chrome Discards UI

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

खास जानकारी

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

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