Chrome DevTools की मदद से एसिंक्रोनस JavaScript को डीबग करना

पर्ल चेन

शुरुआती जानकारी

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

अच्छी बात यह है कि अब Chrome DevTools में आप एसिंक्रोनस JavaScript कॉलबैक का पूरा कॉल स्टैक देख सकते हैं!

एसिंक्रोनस कॉल स्टैक की खास जानकारी.
एसिंक्रोनस कॉल स्टैक के बारे में खास जानकारी. (हम जल्द ही इस डेमो की प्रोसेस को अलग करेंगे.)

DevTools में एसिंक्रोनस कॉल स्टैक की सुविधा चालू करने के बाद, आप अलग-अलग समय पर अपने वेब ऐप्लिकेशन की स्थिति में ड्रिल कर पाएंगे. इवेंट को सुनने वाले कुछ लोगों, setInterval,setTimeout, XMLHttpRequest, प्रॉमिस, requestAnimationFrame, MutationObservers वगैरह के लिए, पूरा स्टैक ट्रेस चलाएं.

स्टैक ट्रेस को चलाते समय, रनटाइम के लागू होने के खास पॉइंट पर, किसी भी वैरिएबल की वैल्यू का विश्लेषण भी किया जा सकता है. यह आपके वॉच एक्सप्रेशन के लिए एक टाइम मशीन की तरह है!

आइए, इस सुविधा को चालू करके इनमें से कुछ स्थितियों पर एक नज़र डालें.

Chrome में एसिंक्रोनस डीबगिंग चालू करें

इस नई सुविधा को Chrome में चालू करके इसे आज़माएं. Chrome कैनरी DevTools के सोर्स पैनल पर जाएं.

दाईं ओर कॉल स्टैक पैनल के बगल में, "एक साथ काम नहीं करने वाली प्रोसेस" के लिए एक नया चेकबॉक्स दिया गया है. एसिंक्रोनस डीबगिंग को चालू या बंद करने के लिए चेकबॉक्स को टॉगल करें. (हालांकि, यह चालू होने के बाद, हो सकता है कि आप इसे कभी बंद न करना चाहें.)

एक साथ काम नहीं करने वाली प्रोसेस को चालू या बंद करने के लिए टॉगल करें.

देर से टाइमर वाले इवेंट और XHR रिस्पॉन्स को कैप्चर करें

आपने शायद इसे पहले Gmail में पहले देखा होगा:

Gmail, ईमेल भेजने की फिर से कोशिश कर रहा है.

अगर अनुरोध भेजने में कोई समस्या आती है (या तो सर्वर में समस्या हो रही है या क्लाइंट साइड में नेटवर्क कनेक्टिविटी की समस्या है), तो Gmail कुछ समय बाद टाइम आउट होने के बाद, अपने-आप मैसेज को फिर से भेजने की कोशिश करेगा.

यह देखने के लिए कि एसिंक्रोनस कॉल स्टैक देरी से टाइमर इवेंट और XHR रिस्पॉन्स का विश्लेषण करने में कैसे हमारी मदद कर सकते हैं, मैंने मॉक Gmail उदाहरण के साथ उस फ़्लो को फिर से बनाया है. पूरा JavaScript कोड ऊपर दिए गए लिंक में मिल सकता है, लेकिन उसका फ़्लो इस तरह है:

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

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

पहले
Gmail के मॉक उदाहरण में सेट किया गया ब्रेकपॉइंट, जिसमें एक साथ काम न करने वाली कॉल स्टैक नहीं है.
कॉल स्टैक पैनल, जिसमें एसिंक्रोनस चालू के बिना मौजूद है.

यहां देखा जा सकता है कि postOnFail() को AJAX कॉलबैक से शुरू किया गया था, लेकिन कोई और जानकारी नहीं है.

इसके बाद
Gmail के मॉक उदाहरण में सेट किया गया ब्रेकपॉइंट, जिसमें एक साथ काम न करने वाली कॉल स्टैक की सुविधा है.
एसिंक्रोनस चालू के साथ कॉल स्टैक पैनल चालू है.

यहां देखा जा सकता है कि XHR को submitHandler() से शुरू किया गया था. बढ़िया!

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

submitHandler()
Gmail के मॉक उदाहरण में सेट किया गया ब्रेकपॉइंट, जिसमें एक साथ काम न करने वाली कॉल स्टैक की सुविधा है
retrySubmit()
Gmail के मॉक उदाहरण में सेट किया गया एक और ब्रेकपॉइंट, जिसमें एक साथ काम न करने वाली कॉल स्टैक की सुविधा है

एसिंक्रोनस तरीके से एक्सप्रेशन देखें

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

aysnc कॉल स्टैक के साथ वॉच के एक्सप्रेशन इस्तेमाल करने का उदाहरण

पिछले दायरों के कोड का आकलन करें

एक्सप्रेशन को देखने के अलावा, सीधे DevTools JavaScript कंसोल पैनल में पिछले दायरों से, अपने कोड से इंटरैक्ट किया जा सकता है.

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

aysnc कॉल स्टैक के साथ JavaScript कंसोल का इस्तेमाल करने का उदाहरण.
अपने कोड को डीबग करने के लिए, एसिंक्रोनस कॉल स्टैक के साथ JavaScript कंसोल का इस्तेमाल करें. ऊपर दिया गया डेमो यहां देखा जा सकता है.

अपने एक्सप्रेशन में बदलाव करने के लिए DevTools में मौजूद रहने से आपको अपने सोर्स कोड पर वापस स्विच करने, बदलाव करने, और ब्राउज़र को रीफ़्रेश करने का समय नहीं मिलेगा.

एक-दूसरे से जुड़े प्रॉमिस का समाधान करें

अगर आपको लगता है कि एसिंक्रोनस कॉल स्टैक की सुविधा को चालू किए बिना, Gmail के पिछले मॉक फ़्लो को ठीक करना मुश्किल है, तो क्या आप कल्पना कर सकते हैं कि 'एक ही जगह से चलने वाले वादों' जैसे ज़्यादा जटिल एसिंक्रोनस फ़्लो के साथ कितना मुश्किल होगा? चलिए, JavaScript Promises पर जेक आर्किबाल्ड के ट्यूटोरियल के आखिरी उदाहरण पर दोबारा नज़र डालते हैं.

यहां जेक के async-Best-example.html उदाहरण में, कॉल स्टैक चलने का एक छोटा सा ऐनिमेशन दिखाया गया है.

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

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

इसके बाद
प्रॉमिस में सेट किया गया ब्रेकपॉइंट, जैसे कि एक साथ काम नहीं करने वाली कॉल स्टैक की सुविधा.
एसिंक्रोनस चालू के साथ कॉल स्टैक पैनल चालू है.

वाह! ऐसे वादे. ज़्यादातर कॉलबैक.

अपने वेब ऐनिमेशन के बारे में अहम जानकारी पाएं

आइए, HTML5Rocks के संग्रहों के बारे में ज़्यादा जानते हैं. क्या आपको पॉल लुइस का Leaner, Meaner, Quick Animations with requestAnimationFrame याद है?

requestAnimationFrame डेमो खोलें. साथ ही, post.html की update() तकनीक (लाइन 874 के आस-पास) की शुरुआत में ब्रेकपॉइंट जोड़ें. एक साथ सिंक करने वाले कॉल स्टैक की मदद से, हमें requestAnimationFrame के बारे में काफ़ी अहम जानकारी मिलती है. इसमें, शुरुआती स्क्रोल इवेंट कॉलबैक पर वापस जाने की सुविधा शामिल है.

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

म्यूटेशन ऑब्ज़र्वर का इस्तेमाल करते समय DOM अपडेट ट्रैक करें

MutationObserver की मदद से, हम DOM में हुए बदलावों पर नज़र रख सकते हैं. इस आसान उदाहरण में, बटन पर क्लिक करने पर, <div class="rows"></div> में एक नया डीओएम नोड जोड़ दिया जाता है.

Demo.html में nodeAdded() (लाइन 31) में एक ब्रेकपॉइंट जोड़ें. एसिंक्रोनस कॉल स्टैक की सुविधा चालू होने पर, अब कॉल स्टैक को addNode() से होते हुए शुरुआती क्लिक इवेंट पर ले जाया जा सकता है.

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

एसिंक्रोनस कॉल स्टैक में JavaScript को डीबग करने के लिए सलाह

अपने फ़ंक्शन को नाम दें

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

उदाहरण के लिए, इस तरह का कोई अनाम फ़ंक्शन लें:

window.addEventListener('load', function() {
  // do something
});

और इसे windowLoaded() जैसा कोई नाम दें:

window.addEventListener('load', function <strong>windowLoaded</strong>(){
  // do something
});

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

पहचान छिपाने वाला फ़ंक्शन.
से पहले
नाम वाला फ़ंक्शन
के बाद

ज़्यादा एक्सप्लोर करें

आपको याद दिला दें कि ये सभी एसिंक्रोनस कॉलबैक हैं, जिनमें DevTools पूरा कॉल स्टैक दिखाएगा:

  • टाइमर: वापस वहां जाएं जहां setTimeout() या setInterval() को शुरू किया गया था.
  • XHR: वापस वहां जाएं जहां xhr.send() को कॉल किया गया था.
  • ऐनिमेशन फ़्रेम: जहां requestAnimationFrame को कॉल किया गया था वहां वापस जाएं.
  • प्रॉमिस: वापस उस जगह पर जाएं जहां वादा पूरा किया गया था.
  • Object.observe: उस जगह पर वापस जाएं जहां से ऑब्ज़र्वर कॉलबैक मूल रूप से बाउंड था.
  • MutationObservers: वापस उस जगह पर जाएं जहां से म्यूटेशन ऑब्ज़र्वर इवेंट ट्रिगर हुआ था.
  • window.postMessage(): इंट्रा-प्रोसेस मैसेजिंग कॉल पर जाएं.
  • DataTransferItem.getAsString()
  • फ़ाइल सिस्टम एपीआई
  • IndexedDB
  • WebSQL
  • addEventListener() के ज़रिए स्वीकार किए गए DOM इवेंट: इवेंट के ट्रिगर होने की जगह पर जाएं. परफ़ॉर्मेंस की वजहों से, सभी डीओएम इवेंट, एक साथ काम करने वाली कॉल स्टैक की सुविधा के लिए ज़रूरी शर्तें पूरी नहीं करते. फ़िलहाल उपलब्ध इवेंट के उदाहरण में ये शामिल हैं: 'scroll', 'hashchange', और 'selectionchange'.
  • addEventListener() के ज़रिए मल्टीमीडिया इवेंट: वापस उस जगह पर जाएं जहां इवेंट ट्रिगर हुआ था. उपलब्ध मल्टीमीडिया इवेंट में ये इवेंट शामिल हैं: ऑडियो और वीडियो इवेंट (जैसे कि 'play', 'pause', 'ratechange'), WebRTC MediaStreamTrackList इवेंट (जैसे कि 'addtrack', 'removetrack'), और MediaSource इवेंट (उदाहरण के लिए, 'sourceopen') हैं.

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

इसे Chrome में आज़माएं. अगर आपको इस नई सुविधा के बारे में कोई सुझाव/राय देनी है या शिकायत करनी है, तो Chrome DevTools गड़बड़ी के ट्रैकर या Chrome DevTools ग्रुप में हमें एक लाइन छोड़ें.