रिएक्ट कैश, टाइम स्लाइसिंग और सिंक्रोनस एपीआई फ़ेचिंग में गहराई से उतरें
<पी> मार्विन फ़्रैचेट द्वारा <पी> ख़ैर, यह साल रिएक्ट का साल लगता है। आपने शायद नए किलर फ़ीचर के बारे में सुना होगा जो 16.7-अल्फ़ा.0 - हुक्स के साथ आ रहा है। आपने शायद टाइम स्लाइसिंग या यहां तक कि सस्पेंस जैसी कुछ अन्य बेहतरीन और बढ़िया चीज़ों के बारे में भी सुना होगा। <पी> यह लेखनहींहै इसका उद्देश्य यह वर्णन करना है कि कुछ नई सुविधाओं का उपयोग कैसे किया जाए, बल्कि यह साबित करना है कि उनका निर्माण कैसे किया गया होगा। सिर्फ यह समझने के लिए कि हम किसके साथ खेल रहे हैं। <पी> यह उस तरीके से भी लिखा गया है जिस तरह से मैंने फीचर की खोज की है। संभवतः यह उस तरह से नहीं है जिस तरह से इसके बारे में सोचा गया है, लेकिन इस तरह से मुझे अंक मिले। <पी> पढ़ते समय आपको क्या मिलेगा: - Async जावास्क्रिप्ट और इवेंट लूप
- प्रतिक्रिया में बीजगणितीय प्रभाव, उदाहरण के साथ
- फाइबर और प्रतिक्रिया चरण
मैंने यह पोस्ट क्यों लिखी?
<पी> जिस चीज़ ने मुझे यह पोस्ट लिखने के लिए प्रेरित किया वह यह विशेष और प्रयोगात्मक सुविधा थी जो एसिंक्रोनस के उपयोग की अनुमति देती है सिंक्रोनस का उपयोग करके संचालन एपीआई: <पी> const bulbasaur = ApiResource.read() ?…क्या? सिंक्रोनस ?! <पी> रिएक्ट-कैश लाइब्रेरी एक सिंक्रोनस एपीआई के साथ एसिंक्रोनस ऑपरेशंस का उपयोग करने की क्षमता बनाती है। यह वह विशेषता है जिसने मुझे यह जानने के लिए प्रेरित किया कि रिएक्ट हुड के तहत कैसे काम कर रहा है। इस लाइब्रेरी पर डैन अब्रामोव और एंड्रयू क्लार्क द्वारा प्रस्तुत एक प्रस्तुति है: <पी> यह कैसे संभव है? हम सिंक्रोनस कॉल का उपयोग करके कुछ दूरस्थ डेटा कैसे प्राप्त कर सकते हैं? <पी> आइए इस उदाहरण पर गहराई से गौर करें और यह समझने की कोशिश करें कि रिएक्ट-कैश ऐसी कार्यक्षमता को कैसे कार्यान्वित करता है और पता लगाता है कि यह कैसे काम कर सकता है। यह कहानी फ़ाइबर आर्किटेक्चर से शुरू होती है। जावास्क्रिप्ट संचालन को नियंत्रित करना
<पी> फ़ाइबर आर्किटेक्चर रिएक्ट को कार्य निष्पादन पर नियंत्रण रखने की अनुमति देता है। इसे रिएक्ट द्वारा झेली गई कई समस्याओं को हल करने के लिए बनाया गया है। यहां वे दो हैं जिन्होंने मेरा ध्यान खींचा: - विशिष्ट घटनाओं पर प्राथमिकता देना, जैसे डेटा लाने पर उपयोगकर्ता इनपुट
- मुख्य थ्रेड की उपलब्धता को बनाए रखने और लंबी रेंडरिंग प्रक्रियाओं के दौरान इसे ब्लॉक करने से बचने के लिए रिएक्ट गणना को अतुल्यकालिक रूप से विभाजित करना
<पी> वह सब कुछ जो स्थिति परिवर्तन को ट्रिगर करता है - न केवल रिएक्ट के साथ - जावास्क्रिप्ट एप्लिकेशन के अंदर अतुल्यकालिक संचालन के कारण होता है। इनमें setTimeout शामिल है , fetch , और घटनाओं के श्रोता। <पी> एसिंक्रोनस ऑपरेशंस को कई जावास्क्रिप्ट कोर अवधारणाओं के माध्यम से प्रबंधित किया जाता है: - कार्य (माइक्रो, मैक्रो, रेंडर आदि...)
- इवेंट लूप
- कॉलस्टैक
<पी> यदि आप इन अवधारणाओं से परिचित नहीं हैं, तो मेरा सुझाव है कि आप जेक आर्चीबाल्ड का यह वीडियो देखें: <पी> फ़ाइबर के लिए धन्यवाद, उपयोगकर्ता इनपुट का समाधान किया जाता है फ़ेच कॉल जैसे अन्य एसिंक्रोनस ऑपरेशन से पहले। <पी> यह कैसे संभव है? <पी> खैर, ऊपर आर्चीबाल्ड की बातचीत इवेंट लूप कैसे काम करती है, इसके बारे में सीखने के मेरे अपने रास्ते का पहला पत्थर था। उनका कहना है कि सूक्ष्म कार्य - उदाहरण के लिए, प्रॉमिस एपीआई के माध्यम से उत्पन्न होते हैं - निष्पादित किए जाते हैं और पहले फ्लश किए जाते हैं अगला मैक्रो कार्य. यह प्रक्रिया setTimeout जैसी कॉलबैक-आधारित विधियों का उपयोग करती है . <पी> इसलिए, यदि आपको मेरी "उपयोगकर्ता इनपुट बनाम डेटा प्राप्त करना" तुलना याद है, तो टीम ने fetch कैसे बनाया संकल्प बाद में onChange संकल्प? <पी> इनमें से कोई भी अवधारणा एक ही विशिष्टता, WhatWG / HTML5 / Ecma-262 में फिट नहीं होती है, और ब्राउज़र या JS इंजन जैसे विभिन्न स्थानों से प्रदान की जाती है। <पी> मेरा मतलब है, हमें Promise को कैसे हल करना चाहिए setTimeout के बाद ? <पी> यह मुझे बिल्कुल पागलपन जैसा लग रहा था और यह अंदाजा लगाना वाकई मुश्किल था कि यह कैसे काम कर सकता है। सच तो यह है कि यह उच्च स्तर पर होता है। <पी> बाद में, मैंने रिएक्ट रैली में ब्रैंडन डेल की अविश्वसनीय बातचीत देखी। यह नई टाइम स्लाइसिंग और सस्पेंस सुविधाओं को प्रस्तुत करता है जिन्हें रिएक्ट फाइबर आर्किटेक्चर के लिए धन्यवाद दिया गया है: <पी> डेल के अनुसार, फाइबर सामान्य जावास्क्रिप्ट कॉलस्टैक की तरह ही है जहां स्टैक में प्रत्येक आइटम को फाइबर कहा जाता है। . यह उस कॉलस्टैक से भिन्न है जो फ़्रेम पर निर्भर करता है जो फ़ंक्शन (+ मेटाडेटा) का प्रतिनिधित्व करता है बल्कि, एक फ़ाइबर एक घटक (+ मेटाडेटा) का प्रतिनिधित्व करता है . आइए फ़ाइबर को एक घटक के चारों ओर एक विशाल बॉक्स के रूप में देखें जो इसके बारे में सब कुछ जानता है। <पी> इन दोनों अवधारणाओं के बीच एक महत्वपूर्ण अंतर है। <पी> पहली ओर, कॉलस्टैक एक ऐसी कार्यक्षमता है जिसे मूल भाग ड्राइविंग के शीर्ष पर बनाया गया है। जावास्क्रिप्ट कोड . इसका लक्ष्य प्रत्येक जावास्क्रिप्ट फ़ंक्शन कॉल को स्टैक करना और उन्हें अपने आप चलाना है। हर बार जब हम किसी फ़ंक्शन को कॉल करते हैं तो यह स्टैक में जुड़ जाता है। कॉलस्टैक के बिना, हम स्पष्ट और विस्तृत त्रुटि स्टैकट्रैस प्राप्त करने में सक्षम नहीं होंगे। और चूँकि कॉलस्टैक जावास्क्रिप्ट कोड से उपलब्ध नहीं है, इसलिए इस पर नियंत्रण रखना वास्तव में कठिन और असंभव भी है। <पी> दूसरी ओर, फ़ाइबर - फ़ाइबर के ढेर की तरह - एक ही अवधारणा का प्रतिनिधित्व करते हैं, लेकिन जावास्क्रिप्ट कोड में निर्मित होते हैं। सबसे छोटी इकाई कार्य नहीं, बल्कि एक घटक है. यह वास्तव में जावास्क्रिप्ट ब्रह्मांड में चलता है। <पी> तथ्य यह है कि फाइबर आर्किटेक्चर पूरी तरह से जावास्क्रिप्ट में बनाया गया है, इसका मतलब है कि हम इसका उपयोग कर सकते हैं, इसे एक्सेस कर सकते हैं और इसे संशोधित कर सकते हैं। हम मानक जावास्क्रिप्ट का उपयोग करके इस पर काम कर सकते हैं। <पी> जो चीज मुझे गलत दिशा में ले गई, वह यह थी कि मुझे लगा कि रिएक्ट जावास्क्रिप्ट के काम करने के आंतरिक तरीके को खत्म करने के लिए वर्कअराउंड का उपयोग कर रहा है। ऐसा नहीं है . फ़ाइबर केवल जावास्क्रिप्ट ऑब्जेक्ट हैं जिनके पास रिएक्ट घटकों के बारे में जानकारी होती है और जो उनके जीवनचक्र के साथ बातचीत कर सकते हैं। यह केवल रिएक्ट की आंतरिक कार्यप्रणाली पर कार्य कर सकता है। <पी> यह विचार नहीं है पुन:परिभाषित करने के लिए कि जावास्क्रिप्ट को कैसे काम करना चाहिए, जैसे यह बताना कि fetch कॉलबैक कार्यों से पहले माइक्रोटास्क रिज़ॉल्यूशन निष्पादित किया जाना चाहिए। यह इस बात पर अधिक निर्भर करता है कि कौन से रिएक्ट तरीकों को कहा जाना चाहिए या नहीं एक विशिष्ट संदर्भ में, जैसे विभिन्न जीवनचक्र विधि कॉलों को बाधित करना। <पी> अरे रुको! आप कहते हैं कि फ़ाइबर किसी रिएक्ट ऐप में हर चीज़ को बिल्कुल नियंत्रित कर सकता है? लेकिन कोई घटक रिएक्ट को कुछ भी करने से रोकने के लिए कैसे कह सकता है? बीजगणितीय प्रभाव, हाँ, लेकिन कृपया जावास्क्रिप्ट में
<पी> फाइबर आर्किटेक्चर की बदौलत रिएक्ट घटकों को नियंत्रित करने और यह जानने में सक्षम है कि कोई घटक चल रहा है या नहीं। अब जो गायब है वह रिएक्ट को यह बताने का एक तरीका है कि किसी विशिष्ट घटक के लिए कुछ बदल गया है, इसलिए वह इस बदलाव को संभाल लेगा। <पी> यहीं पर बीजगणितीय प्रभाव पड़ता है खेल में प्रवेश करें. <पी> बीजगणितीय प्रभाव कोई ऐसी चीज़ नहीं है जो जावास्क्रिप्ट में मौजूद है। मैं उच्च स्तरीय स्पष्टीकरण के साथ यह समझाने का प्रयास करूंगा कि वे क्या हैं। <पी> बीजगणितीय प्रभाव एक अवधारणा है जो कुछ जानकारी कहीं भेजने की अनुमति देती है, कुछ हद तक एक डिस्पैचर की तरह। विचार यह है कि एक विशिष्ट फ़ंक्शन को कॉल किया जाए जो विकाध करेगा वर्तमान में चल रहा फ़ंक्शन एक सटीक स्थिति में है ताकि मूल फ़ंक्शन किसी गणना को संभाल सके। जब मूल गणना समाप्त हो जाती है, तो यह प्रोग्राम को प्रारंभिक स्थिति में फिर से शुरू कर सकता है जहां जानकारी भेजी गई है। <पी> OCaml या Eff जैसी कुछ भाषाएँ इन सुविधाओं से मूल रूप से लाभान्वित होती हैं। यह वास्तव में एक दिलचस्प निष्कर्ष है क्योंकि कार्यान्वयन विवरण केवल मूल पर निर्भर करता है: <पी> क्या जावास्क्रिप्ट में ऐसी सुविधा होना अद्भुत नहीं होगा? <पी> रिएक्ट टीम ने जावास्क्रिप्ट try/catch से संबंधित रिएक्ट संदर्भ में एक समान दृष्टिकोण बनाया है ब्लॉक. डेल के अनुसार, यह जावास्क्रिप्ट में सबसे निकटतम उपलब्ध अवधारणा है। <पी> कुछ फेंकने से माता-पिता को कहीं न कहीं जानकारी भेजने की अनुमति मिलती है। सबसे पहले माता-पिता जो जानकारी पकड़ते हैं, वे उससे निपटने और उस पर गणना करने में सक्षम होते हैं। एक उदाहरण हज़ार शब्दों से बेहतर है
<पी> निम्नलिखित कोड की कल्पना करें जो एक सिंक्रोनस एपीआई का उपयोग करके बुलबासौर लाने का प्रयास करता है : <पी> कोड का यह टुकड़ा अजीब हो सकता है क्योंकि सिंक्रोनस एपीआई का उपयोग करके डेटा प्राप्त करना वास्तव में आम नहीं है। आइए customFetch के अंदर कूदें फ़ंक्शन कार्यान्वयन: <पी> ओह रुको! यह बिल्कुल किसी भ्रूण की तरह नहीं दिखता है! मुझे बिल्कुल भी समझ नहीं आ रहा है कि इस फ़ंक्शन का उद्देश्य क्या है... <पी> खैर, घटक के आसपास कुछ कल्पना करें , मान लीजिए कि एक फ़ाइबर ऐसा दिखता है: <पी> कोड को पढ़ने के लिए कुछ समय लें। <पी> अब, आइए customFetch पर जाएं कार्यान्वयन: <पी> पिछले स्निपेट में महत्वपूर्ण भाग try/catch है ब्लॉक. <पी> आइए संक्षेप में बताएं कि कोड के इन विभिन्न टुकड़ों के माध्यम से क्या हो रहा है: - द
Pokemon घटक customFetch को कॉल करता है विधि.
- द
customFetch विधि इसके आंतरिक कैश को पढ़ने का प्रयास करती है, लेकिन यह खाली है। तो यह कुछ न कुछ / कहीं न कहीं फेंकता है - बीजगणितीय प्रभाव।
- द
fiber माता-पिता उस जानकारी को पकड़ते हैं, उसे संभालते हैं, और डेटा लाते हैं। फिर यह customFetch को पॉप्युलेट करता है डेटा के साथ कैश करें.
- एक पुनः रेंडर
Component(args) में होता है और, अब, customFetch कैश भर गया है. डेटा अब सिंक्रोनस एपीआई का उपयोग करके घटक में उपलब्ध है।
<पी> react-cache पर एक नज़र डालें कार्यान्वयन विवरण और विभिन्न थ्रो की जाँच करें। <पी> इस प्रक्रिया के दौरान किसी चीज़ ने आपका ध्यान खींचा होगा:render दो बार बुलाया गया है. त्रुटि फेंकने के लिए एक - रोकना घटक - और एक डेटा प्राप्त करने के लिए - फिर से शुरू करना घटक. रिएक्ट के साथ एकाधिक render को ट्रिगर करना ठीक है कॉल करता है क्योंकि यह पूरी तरह से एक शुद्ध कार्य है - इसका अपने आप में कोई दुष्प्रभाव नहीं है। <पी> रुको... क्या? render कोई साइड इफेक्ट तो नहीं है? DOM के बारे में क्या? प्रतिक्रिया चरण
<पी> यदि आप लंबे समय से रिएक्ट के साथ काम कर रहे हैं, तो आपने सुना होगा कि कई बार पुन:प्रस्तुत करना अच्छा अभ्यास नहीं है। फाइबर आर्किटेक्चर से पहले, हर बार जब हम रेंडर फ़ंक्शन को कॉल करते थे तो रिएक्ट कुछ आंतरिक गणना करता था और फिर उसके अनुसार DOM को संशोधित करता था। उदाहरण के लिए, setState के माध्यम से रेंडर फ़ंक्शन को कॉल करते समय ऐसा हुआ . प्रक्रिया इनलाइन थी: <पी> setState →render → वर्चुअल नोड्स की तुलना करें → DOM नोड्स को अपडेट करें <पी> फाइबर से निपटने की प्रक्रिया थोड़ी अलग है। इसने कतार और बैचों की एक अवधारणा पेश की है जो उच्च प्रदर्शन DOM संशोधनों की अनुमति देती है। <पी> विचार काफी सरल है. हम मानते हैं कि स्क्रीन ~60 फ़्रेम प्रति सेकंड चल सकती हैं। इस धारणा से, और उपलब्ध जावास्क्रिप्ट फ़ंक्शंस का उपयोग करके, केवल प्रत्येक ~16.7ms पर कुछ गणनाएँ और DOM संशोधन करना संभव है। फाइबर के साथ, रिएक्ट कई संशोधनों को सूचीबद्ध कर सकता है और उन्हें प्रति सेकंड लगभग 60 बार प्रतिबद्ध कर सकता है। <पी> इस प्रकार के संशोधन ने रिएक्ट को अपने फायदे और विशिष्टताओं के साथ तीन चरणों में विभाजित करने की अनुमति दी है: <पी>
_[डैन अब्रामोव रिएक्ट के संबंध में चरण](https://twitter.com/dan_abramov/status/981712092611989509/photo/1?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwter m%5E981712092611989509&ref_url=https%3A%2F%2Fmedium.com%2Fmedia%2Fbda1c34a16e9f8a8e3eb244716a1da72%3FpostId%3D2a57dc9c2e6d" rel='noopener' target='खाली' शीर्षक=') पी> - रेंडर चरण शुद्ध और नियतात्मक है। इसका कोई साइड इफेक्ट नहीं है और जिन विभिन्न कार्यों से यह बना है, उन्हें कई बार बुलाया जा सकता है। रेंडर चरण बाधित है — यह
render नहीं है वह फ़ंक्शन जो विराम मोड में है, लेकिन संपूर्ण चरण
- प्री-कमिट वाक्यांश का उद्देश्य रीड मोड में वास्तविक DOM स्थिति, जैसे स्क्रॉलबार स्थिति, तक पहुंच प्रदान करना है।
- प्रतिबद्ध चरण वास्तव में DOM को संशोधित करता है और बाधित नहीं है . उस चरण के दौरान प्रतिक्रिया रुक नहीं सकती।
<पी> तीन चरणों के इस सेट ने टाइम स्लाइसिंग क्षमताओं को पेश किया है। रिएक्ट रेंडर चरण के दौरान दो घटक फ़ंक्शन कॉल के बीच रुकने और आवश्यक होने पर उस चरण को फिर से शुरू करने में सक्षम है। <पी> फाइबर में, render इसका लक्ष्य केवल नवीनतम उपलब्ध प्रतिनिधित्व प्राप्त करना है किसी घटक की आंतरिक स्थिति के आधार पर कुछ तुलनाएँ करें और जानें कि रिएक्ट को DOM बदलना है या नहीं। यदि प्रतिबद्ध संशोधन की आवश्यकता है, तो यह संशोधन को "कार्य प्रगति पर" कतार में जोड़ देगा। <पी> रिएक्ट समवर्ती (टाइम स्लाइसिंग + सस्पेंस) और फाइबर आर्किटेक्चर की बदौलत रिएक्ट टीम ने प्रदर्शन में भारी सुधार किया है। उन्होंने इवेंट प्राथमिकताकरण और समवर्तीता जैसी विभिन्न ब्राउज़र समस्याओं का मुकाबला करने के लिए वर्कअराउंड बनाए हैं। <पी> यदि हम एक कदम पीछे हटते हैं, तो क्या उन्होंने यही नहीं दिखाया है? ब्राउज़र और फ्रंट-एंड फ्रेमवर्क के लिए प्राथमिकता नई चुनौती प्रतीत होती है। <पी> अन्य टीमें भी कला की वास्तविक स्थिति को बेहतर बनाने पर काम कर रही हैं और यहां तक कि भविष्य के एपीआई का प्रस्ताव भी दे रही हैं। यह Google का विचार है: <पी> मुफ़्त में कोड करना सीखें. फ्रीकोडकैंप के ओपन सोर्स पाठ्यक्रम ने 40,000 से अधिक लोगों को डेवलपर्स के रूप में नौकरी पाने में मदद की है। आरंभ करें