अपडेट 10/9/2013: रन लूप के इस इंटरैक्टिव विज़ुअलाइज़ेशन की जाँच करें: https://machty.s3.amazonaws.com/ember-run-loop-visual/index.html
अद्यतन 5/9/2013: नीचे दी गई सभी बुनियादी अवधारणाएँ अभी भी अद्यतित हैं, लेकिन इस प्रतिबद्ध के अनुसार , एम्बर रन लूप कार्यान्वयन को एक अलग पुस्तकालय में विभाजित किया गया है जिसे बैकबर्नर.जेएस कहा जाता है , जिसमें कुछ बहुत ही मामूली एपीआई अंतर हैं।
सबसे पहले, इन्हें पढ़ें:
http://blog.sproutcore.com/the-run-loop-part-1/
http://blog.sproutcore.com/the-run-loop-part-2/
वे एम्बर से 100% सटीक नहीं हैं, लेकिन रनऑलॉप के पीछे मुख्य अवधारणाएं और प्रेरणा अभी भी आम तौर पर एम्बर पर लागू होती हैं; केवल कुछ कार्यान्वयन विवरण अलग हैं। लेकिन, आपके सवालों पर:
एम्बर रनलूप कब शुरू होता है। क्या यह राउटर या व्यूज या कंट्रोलर्स या किसी और चीज पर निर्भर है?
सभी मूल उपयोगकर्ता ईवेंट (जैसे कीबोर्ड ईवेंट, माउस ईवेंट, आदि) रन लूप को आग देंगे। यह गारंटी देता है कि कैप्चर किए गए (माउस / कीबोर्ड / टाइमर / आदि) इवेंट द्वारा बाध्य गुणों के लिए जो भी परिवर्तन किए गए हैं, वे सिस्टम पर नियंत्रण वापस करने से पहले एम्बर के डेटा-बाइंडिंग सिस्टम में पूरी तरह से प्रचारित हैं। तो, अपने माउस को ले जाना, एक कुंजी दबाकर, एक बटन क्लिक करना आदि, सभी रन लूप लॉन्च करते हैं।
लगभग कितना समय लगता है (मुझे पता है कि यह पूछने के लिए मूर्खतापूर्ण है और कई चीजों पर निर्भर है लेकिन मैं एक सामान्य विचार की तलाश कर रहा हूं, या हो सकता है कि अगर कोई न्यूनतम या अधिकतम समय एक रनअप ले सकता है)
किसी भी बिंदु पर RunLoop कभी भी ट्रैक नहीं रखेगा कि सिस्टम के माध्यम से सभी परिवर्तनों को प्रचारित करने में कितना समय लग रहा है और फिर अधिकतम समय सीमा तक पहुंचने के बाद RunLoop को रोक दें; इसके बजाय, RunLoop हमेशा पूरा करने के लिए चलेगा, और तब तक नहीं रुकेगा जब तक कि सभी समयसीमा समाप्त नहीं हो गई है, बाइंडिंग प्रचारित किया गया है, और शायद उनके बाइंडिंग ने प्रचार किया, और इसी तरह। जाहिर है, जितने अधिक परिवर्तन एक ही घटना से प्रचारित करने की जरूरत है, रनऑलॉप को खत्म करने में उतना ही अधिक समय लगेगा। यहां एक और (बहुत अनुचित) उदाहरण दिया गया है कि कैसे रनऑलॉप एक अन्य ढांचे (बैकबोन) की तुलना में प्रचार परिवर्तनों से टकरा सकता है जिसमें एक रन लूप नहीं है: http://jsfiddle.net/jashkenas/CGSd5/। मोरल ऑफ़ द स्टोरी: रनऑलॉप का वास्तव में सबसे तेज़ चीज़ों के लिए तेज़ जो आप कभी एम्बर में करना चाहते हैं, और यह वह जगह है जहाँ एम्बर की बहुत शक्ति निहित है, लेकिन यदि आप स्वयं को 60 फ्रेम प्रति सेकंड पर जावास्क्रिप्ट के साथ 30 सर्कल को चेतन करना चाहते हैं, तो एम्बर के रनऑलॉप पर भरोसा करने की तुलना में इसके बारे में बेहतर तरीके हो सकते हैं।
क्या रनऑलॉप को हर समय निष्पादित किया जा रहा है, या यह केवल निष्पादन की शुरुआत से अंत तक की अवधि का संकेत दे रहा है और कुछ समय के लिए नहीं चल सकता है।
इसे हर समय निष्पादित नहीं किया जाता है - इसे किसी बिंदु पर सिस्टम पर वापस नियंत्रण वापस करना पड़ता है या फिर आपका ऐप लटका रहता है - यह अलग है, कहते हैं, एक सर्वर पर एक रन लूप है जो एक है while(true)
और अनंत तक चलता है सर्वर को बंद करने के लिए एक संकेत मिलता है ... एम्बर रनऑलॉप में ऐसा while(true)
नहीं है, लेकिन उपयोगकर्ता / टाइमर घटनाओं के जवाब में केवल काता जाता है।
यदि एक रनऑलॉप से एक दृश्य बनाया जाता है, तो क्या यह गारंटी है कि लूप के समाप्त होने तक इसकी सभी सामग्री इसे DOM में बना देगी?
देखते हैं कि क्या हम इसका पता लगा सकते हैं। SC से Ember RunLoop में बड़े बदलावों में से एक यह है कि, स्प्राउटकोर RL के बारे में पहले लिंक में invokeOnce
और invokeLast
(जो आप आरेख में देखते हैं) के बजाय, Ember आपको 'कतारों' की एक सूची प्रदान करता है, रन लूप का कोर्स, आप क्रियाओं (रन लूप के दौरान बुलाया जाने वाला कार्य) को निर्दिष्ट करके बता सकते हैं कि क्रिया किस कतार में है (स्रोत से उदाहरण:) Ember.run.scheduleOnce('render', bindView, 'rerender');
।
यदि आप run_loop.js
स्रोत कोड को देखते हैं Ember.run.queues = ['sync', 'actions', 'destroy', 'timers'];
, तो आप देखते हैं , फिर भी यदि आप एक एम्बर ऐप में ब्राउज़र में अपना जावास्क्रिप्ट डीबगर खोलते हैं और मूल्यांकन करते हैं Ember.run.queues
, तो आपको कतारों की एक पूरी सूची मिलती है ["sync", "actions", "render", "afterRender", "destroy", "timers"]
:। एम्बर अपने कोडबेस को बहुत मॉड्यूलर रखता है, और वे आपके कोड के साथ-साथ लाइब्रेरी के एक अलग हिस्से में अपने कोड को और अधिक कतारें डालने के लिए संभव बनाते हैं। इस मामले में, एम्बर व्यू लाइब्रेरी आवेषण render
और afterRender
कतार, विशेष रूप से actions
कतार के बाद । मैं एक सेकंड में क्यों हो सकता है। सबसे पहले, RunLoop एल्गोरिथ्म:
RunLoop एल्गोरिथ्म बहुत समान है जैसा कि SC रन लूप लेख में वर्णित है:
- आप अपना कोड RunLoop के बीच चलाते हैं
.begin()
और .end()
, केवल Ember में आप अपना कोड चलाना चाहते हैं Ember.run
, जो आंतरिक रूप से begin
और आपके end
लिए कॉल करेगा । (एम्बर कोड आधार में केवल आंतरिक रन लूप कोड अभी भी उपयोग करता है begin
और end
, इसलिए आपको बस साथ रहना चाहिए Ember.run
)
- बाद
end()
कहा जाता है, RunLoop तो गियर में kicks हर एक के लिए पारित कोड का हिस्सा द्वारा किए गए परिवर्तन लागू होने Ember.run
कार्य करते हैं। इसमें बाध्य गुणों के मूल्यों का प्रचार करना, DOM के लिए दृश्य परिवर्तन प्रदान करना, इत्यादि शामिल हैं। इन कार्यों (बाध्यकारी, DOM तत्वों आदि का प्रतिपादन) के क्रम को Ember.run.queues
ऊपर वर्णित सरणी द्वारा निर्धारित किया जाता है:
- रन लूप पहली कतार पर शुरू होगा, जो है
sync
। यह उन सभी कार्यों को चलाएगा sync
जो Ember.run
कोड द्वारा कतार में निर्धारित किए गए थे । ये क्रियाएं स्वयं भी इसी RunLoop के दौरान किए जाने वाले अधिक कार्यों को शेड्यूल कर सकती हैं, और यह सुनिश्चित करने के लिए RunLoop पर निर्भर है कि यह प्रत्येक क्रिया को तब तक करता है जब तक कि सभी कतार फ़्लश न हो जाएं। जिस तरह से यह होता है, वह प्रत्येक कतार के अंत में, RunLoop पहले की सभी निस्तब्ध कतारों को देखेगा और देखेगा कि क्या कोई नया कार्य निर्धारित किया गया है। यदि ऐसा है, तो इसे बिना किसी निर्धारित क्रिया के जल्द से जल्द कतार की शुरुआत में शुरू करना होगा और कतार से बाहर निकलना होगा, अपने कदमों का पता लगाना जारी रखना चाहिए और जब तक आवश्यक न हो तब तक शुरू करें जब तक कि सभी कतारें पूरी तरह से खाली न हो जाएं।
यही एल्गोरिथ्म का सार है। इस प्रकार ऐप के माध्यम से बाध्य डेटा का प्रचार होता है। आप उम्मीद कर सकते हैं कि एक रनऑलॉप पूरा होने के बाद, सभी बाउंड डेटा को पूरी तरह से प्रचारित किया जाएगा। तो, डोम तत्वों के बारे में क्या?
एम्बर व्यू लाइब्रेरी द्वारा जोड़े गए कतारों का क्रम यहाँ महत्वपूर्ण है। उस पर ध्यान दें render
और afterRender
उसके बाद sync
, और action
। sync
कतार बाध्य डेटा प्रचार के लिए सभी कार्यों में शामिल है। ( action
, उसके बाद, केवल एम्बर स्रोत में ही उपयोग किया जाता है)। उपरोक्त एल्गोरिथ्म के आधार पर, यह गारंटी दी जाती है कि जब तक RunLoop render
कतार में पहुंचता है , तब तक डेटा-बाइंडिंग के सभी सिंक्रनाइज़ेशन समाप्त हो जाएंगे। यह डिज़ाइन द्वारा है: आप पहले DOM तत्वों को रेंडर करने का महंगा काम नहीं करना चाहेंगेडेटा-बाइंडिंग को सिंक करना, क्योंकि इसके बाद अपडेट किए गए डेटा के साथ DOM तत्वों को फिर से प्रस्तुत करना होगा - जाहिर है कि सभी RunLoop कतारों को खाली करने का एक बहुत ही अक्षम और त्रुटि-युक्त तरीका। तो एम्बर समझदारी से सभी डेटा-बाइंडिंग कार्य के माध्यम से विस्फोट करता है जो कि render
क्यू में डोम तत्वों को रेंडर करने से पहले कर सकता है ।
तो, अंत में, अपने प्रश्न का उत्तर देने के लिए, हाँ, आप उम्मीद कर सकते हैं कि किसी भी आवश्यक DOM रेंडरिंग ने समय Ember.run
समाप्त हो गया है। यहाँ एक jsField प्रदर्शित करने के लिए है: http://jsfiddle.net/machty/6p6XJ/328/
RunLoop के बारे में जानने के लिए अन्य बातें
पर्यवेक्षकों बनाम बाइंडिंग
यह ध्यान रखना महत्वपूर्ण है कि ऑब्जर्वर और बाइंडिंग, एक "देखे गए" संपत्ति में परिवर्तनों के जवाब की समान कार्यक्षमता होने के बावजूद, एक RunLoop के संदर्भ में पूरी तरह से अलग व्यवहार करते हैं। बाइंडिंग प्रचार, जैसा कि हमने देखा है, sync
अंततः रनऑलॉप द्वारा निष्पादित करने के लिए कतार में शेड्यूल किया जाता है । दूसरी ओर, पर्यवेक्षकों ने तुरंत देखा कि जब देखी गई संपत्ति पहले बिना रनऑलॉप कतार में निर्धारित किए बिना बदल जाती है। यदि एक पर्यवेक्षक और एक ही संपत्ति के सभी "वॉच" को एक बाध्यकारी करता है, तो पर्यवेक्षक को हमेशा उस समय से 100% कहा जाएगा जब बाध्यकारी से पहले अद्यतन किया जाएगा।
scheduleOnce
तथा Ember.run.once
एम्बर के ऑटो-अपडेटिंग टेम्प्लेट में से एक बड़ी दक्षता को बढ़ावा देता है, इस तथ्य पर आधारित है कि, रनऑलॉप के लिए धन्यवाद, एक समान कार्रवाई में कई समान रनऑलॉप क्रियाओं को coalesced ("बहस" किया जा सकता है, यदि आप करेंगे)। आप इस पर गौर करते हैं run_loop.js
internals, आप कार्यों कि इस व्यवहार को सुविधाजनक बनाने के संबंधित कार्य हैं देखेंगे scheduleOnce
और Em.run.once
। उनके बीच का अंतर इतना महत्वपूर्ण नहीं है क्योंकि वे जानते हैं कि वे मौजूद हैं, और वे रन लूप के दौरान बहुत से फूला हुआ, बेकार गणना को रोकने के लिए कतार में डुप्लिकेट कार्यों को कैसे छोड़ सकते हैं।
टाइमर के बारे में क्या?
भले ही 'टाइमर' ऊपर सूचीबद्ध डिफ़ॉल्ट कतारों में से एक है, लेकिन एम्बर केवल उनके रनअप टेस्ट मामलों में कतार का संदर्भ देता है। ऐसा लगता है कि इस तरह की कतार का इस्तेमाल स्प्राउटकोर दिनों में किया गया होगा जो उपरोक्त लेखों में से कुछ विवरणों के आधार पर टाइमर के बारे में आग लगाने की अंतिम बात है। एम्बर में, timers
कतार का उपयोग नहीं किया जाता है। इसके बजाय, RunLoop को आंतरिक रूप से प्रबंधित setTimeout
ईवेंट ( invokeLaterTimers
फ़ंक्शन देखें ) द्वारा काटा जा सकता है , जो कि सभी मौजूदा टाइमर के माध्यम से लूप करने के लिए पर्याप्त बुद्धिमान है, जो सभी समाप्त हो गए हैं उन्हें आग दें, भविष्य के टाइमर को निर्धारित करें, और एक आंतरिक सेट करेंsetTimeout
केवल उस घटना के लिए, जो आग लगने पर रनऑलॉप को फिर से स्पिन करेगी। प्रत्येक टाइमर कॉल सेटटाइमआउट और खुद को जगाने की तुलना में यह दृष्टिकोण अधिक कुशल है, क्योंकि इस मामले में, केवल एक सेटटाइमआउट कॉल करने की आवश्यकता है, और रनऑलॉप सभी अलग-अलग टाइमर को आग लगाने के लिए पर्याप्त स्मार्ट है जो एक ही समय में बंद हो सकते हैं। समय।
sync
कतार के साथ आगे की बहस
यहां रन लूप से एक स्निपेट है, रन लूप में सभी कतारों के माध्यम से लूप के बीच में। sync
कतार के लिए विशेष मामले पर ध्यान दें : क्योंकि sync
एक विशेष रूप से अस्थिर कतार है, जिसमें डेटा को हर दिशा में प्रचारित किया जा रहा है, Ember.beginPropertyChanges()
किसी भी पर्यवेक्षकों को गोली चलाने से रोकने के लिए कहा जाता है, इसके बाद कॉल किया जाता है Ember.endPropertyChanges
। यह समझदारी है: यदि sync
कतार को फ्लश करने के दौरान , यह पूरी तरह से संभव है कि किसी वस्तु पर एक संपत्ति अपने अंतिम मूल्य पर आराम करने से पहले कई बार बदल जाएगी, और आप हर एक बदलाव के दौरान पर्यवेक्षकों को तुरंत फायरिंग करके संसाधनों को बर्बाद नहीं करना चाहेंगे। ।
if (queueName === 'sync')
{
log = Ember.LOG_BINDINGS;
if (log)
{
Ember.Logger.log('Begin: Flush Sync Queue');
}
Ember.beginPropertyChanges();
Ember.tryFinally(tryable, Ember.endPropertyChanges);
if (log)
{
Ember.Logger.log('End: Flush Sync Queue');
}
}
else
{
forEach.call(queue, iter);
}
उम्मीद है की यह मदद करेगा। मुझे निश्चित रूप से इस बात को लिखने के लिए काफी कुछ सीखना था, जो इस तरह का था।