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

ब्राउज़र के इस्तेमाल से जुड़ी सहायता

  • Chrome: 68.
  • Edge: 79.
  • Firefox: यह सुविधा काम नहीं करती.
  • Safari: यह सुविधा काम नहीं करती.

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

बैकग्राउंड

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

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

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

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

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

पेज लाइफ़साइकल एपीआई, इस समस्या को हल करने की कोशिश करता है:

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

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

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

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

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

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

इस दस्तावेज़ में बताई गई स्थिति और इवेंट फ़्लो की विज़ुअल इमेज.
पेज लाइफ़साइकल एपीआई की स्थिति और इवेंट फ़्लो.

राज्य

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

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

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

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

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

पैसिव

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

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

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

छिपा हुआ

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

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

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

फ़्रीज़ हो गया

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

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

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

इसके बाद की संभावित स्थितियां:
चालू (resume इवेंट के ज़रिए, फिर pageshow इवेंट के ज़रिए)
पैसिव (resume इवेंट के ज़रिए, फिर pageshow इवेंट के ज़रिए)
छिपा हुआ (resume इवेंट के ज़रिए)
खारिज किया गया (कोई इवेंट ट्रिगर नहीं हुआ)

समझौता खत्म हो गया है

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

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

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

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

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

खारिज किया गया स्टेटस में, टैब के शीर्षक और फ़ैविकन के साथ-साथ टैब भी उपयोगकर्ता को दिखता है. भले ही, पेज बंद हो गया हो.

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

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

इवेंट

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

नाम विवरण
focus

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

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

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

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

blur

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

ध्यान दें: 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 कनेक्शन बंद करें.
  • नेटवर्क पोलिंग को रोकें या खुले हुए सभी वेब सॉकेट कनेक्शन बंद करें.
  • सभी वेब लॉक हटाएं.

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

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

Terminated

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

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

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

Discarded

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

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

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

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

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

अनलोड इवेंट

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

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

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

हमारा सुझाव है कि सभी आधुनिक ब्राउज़र में, unload इवेंट के बजाय, संभावित पेज अनलोड (इसे बंद स्थिति भी कहा जाता है) का पता लगाने के लिए, हमेशा pagehide इवेंट का इस्तेमाल करें. अगर आपको 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 Listener को बिना किसी शर्त के जोड़ दिया जाता है:

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);
});

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

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

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

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

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

कुछ मामलों में, 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 फ़्लैग को भी सही तरीके से मैनेज करता है.

खास जानकारी

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

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