2014-05-03 6 views
8

निम्नलिखित JavaScript कोड को ध्यान में रखते:क्यों वादा पुस्तकालय घटना लूप का उपयोग करते हैं?

var promise = new Promise(); 
setTimeout(function() { 
    promise.resolve(); 
}, 10); 

function foo() { } 
promise.then(foo); 

वादा कार्यान्वयन मैंने देखा है में, promise.resolve() बस कुछ संपत्ति वादा इंगित करने के लिए स्थापित करेगा हल किया गया था और foo() एक के दौरान बाद में कहा जा सकता है इवेंट लूप, फिर भी यह वादे की तरह लगता है .resolve() में foo() जैसे किसी भी स्थगित कार्यों को तत्काल कॉल करने के लिए पर्याप्त जानकारी होगी।

इवेंट लूप विधि ऐसा लगता है जैसे यह जटिलता को जोड़ देगा और प्रदर्शन को कम करेगा, तो इसका उपयोग क्यों किया जाता है?

जबकि मेरे अधिकांश वादों का उपयोग जावास्क्रिप्ट के साथ है, मेरे प्रश्न का कारण सी ++ गेम जैसे बहुत ही गहन मामलों में वादे को लागू करने में है, इस मामले में मैं सोच रहा हूं कि क्या मैं कुछ लाभों का उपयोग कर सकता हूं एक घटना लूप के ऊपरी हिस्से के बिना वादे का।

+1

यदि आप तुरंत एक वादा हल करना चाहते हैं, तो आप केवल 'promise.resolve()' पर कॉल करें और वह उस समय किसी भी पंजीकृत हल करने वाले हैंडलर को कॉल करेगा। यदि आप वादा को हल करने से पहले अपने स्वयं के इवेंट लूप को खोलने के लिए चाहते हैं, तो आप 'setTimeout (function() {promise.resolve()}, 10) कर सकते हैं; '। लेकिन, यह इस बात पर निर्भर करता है कि आप '.resolve()' व्यवहार करना चाहते हैं। 'SetTimeout() 'का उपयोग करने की आवश्यकता नहीं है। – jfriend00

+1

हाँ, मैं समझता हूं। मैं समझना चाहता हूं कि सेटटाइमआउट का उपयोग करते समय, 10 मिलीसेकंड्स foo() के तुरंत बाद नहीं कहा जाता है, लेकिन इसके बजाय संकल्प को कतार में रखा जाता है और foo() कुछ समय बाद निष्पादित किया जाता है। – silentorb

+0

कौन सा वादा कार्यान्वयन करता है? कई अलग-अलग कार्यान्वयन हैं इसलिए विशिष्ट कार्यान्वयन के संदर्भ में इस तरह के एक प्रश्न पूछना मुश्किल है। जहां तक ​​मुझे पता है, वहां कोई विनिर्देश नहीं है जो कहता है कि देरी के बाद तक कॉलबैक को हल नहीं किया जाना चाहिए। – jfriend00

उत्तर

9

सभी वादे कार्यान्वयन, कम से कम अच्छे लोग ऐसा करते हैं।

ऐसा इसलिए है क्योंकि एक एसिंक्रोनस एपीआई में समकालिकता मिश्रण releasing Zalgo है।

तथ्य वादे कभी-कभी हल नहीं होते हैं और कभी-कभी स्थगित करने का अर्थ है कि एपीआई सुसंगत है। अन्यथा, निष्पादन के क्रम में आपको अपरिभाषित व्यवहार मिलता है।

function getFromCache(){ 
     return Promise.resolve(cachedValue || getFromWebAndCache()); 
} 

getFromCache().then(function(x){ 
    alert("World"); 
}); 
alert("Hello"); 

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

नोडेटर्मेनिस्टिक निष्पादन आदेश होने से बहुत जोखिम भरा होता है और यह बग का एक आम स्रोत है। वादे/ए + विनिर्देश आपको यहां सफलता के गड्ढे में फेंक रहा है।

+1

इसके लिए क्या लायक है, यहां ऑब्जेक्टिव सी के लिए एक वादा कार्यान्वयन है जिसे मैंने हाल ही में देखा है और अच्छा लग रहा है https://github.com/mxcl/PromiseKit यह वादा/ए + शिकायत –

+1

वादा करता है सभी वादा/ए + अनुपालन नहीं है। इसमें सार्वजनिक रिज़ॉल्यूशन एपीआई नहीं है, इसके बजाय किसी को प्रदान की गई श्रेणियों का उपयोग करने की आवश्यकता है जो कुछ फाउंडेशन वर्गों (जैसे NSURLConnection) (या उन्हें लागू करने की आवश्यकता है) के लिए रिज़ॉल्वर पहलू को लागू करते हैं। इसके अतिरिक्त, जब दिए गए श्रेणियों द्वारा एक वादा हल किया जाएगा, निरंतरता * सिंक्रनाइज़ * कहा जाएगा जो वर्तमान निष्पादन संदर्भ पर हैंडलर को प्रभावी ढंग से निष्पादित करता है - जो कॉल साइट पर ज्ञात नहीं हो सकता है। तो वास्तव में, PromiseKit वास्तव में "टूटा कार्यान्वयन" होगा जिसके बारे में आप बात कर रहे हैं (और मैं सहमत हूं;)) – CouchDeveloper

+2

PromiseKit अब ज़ल्गो जारी नहीं करता है। इसे एक ब्रेक दें, मैंने इसे 4 सप्ताह पहले जारी किया था। – mxcl

2

वादे लगभग cooperative multitasking हैं।

संदेश आधारित शेड्यूलिंग का उपयोग करने के लिए इसे प्राप्त करने के लिए बहुत अधिक एकमात्र तरीका है।

टाइमर (आमतौर पर 0 देरी के साथ) को संदेश कतार में कार्य/संदेश पोस्ट करने के लिए उपयोग किया जाता है - उपज-टू-अगली-कार्य-इन-द-क्यूई पैराडाइम। तो छोटे आयोजन हैंडलर से मिलकर पूरा गठन काम करता है और अधिकतर बार आप उपज करते हैं - यह सब काम सुचारू रूप से।

+0

@ बेंजामिनग्रेनबाम वादे के तरीकों को हल और अस्वीकार कर स्वयं ही असीमित हैं। कॉलर उम्मीद नहीं करेगा कि उन्हें कॉल करते समय इसे काफी समय तक अवरुद्ध कर दिया जाएगा। सुझाए गए तत्काल निष्पादन कॉलर को अवरुद्ध कर सकता है। –

+0

@ बेंजामिनग्रेनबाम, जैसा कि मैंने कहा था, कॉलर को निष्पादन निष्पादन को हल/अस्वीकार कर अवरुद्ध नहीं किया जाएगा। प्रत्येक कार्य को अपना समय सीमा दिया जाता है: कॉलर कोड अपनी सामग्री को संभालता है और पूर्ति कोड अलग निष्पादन फ्रेम (कार्य, टाइमर ईवेंट हैंडलर) में चलता है। अन्यथा उचित मल्टीटास्किंग हासिल करना काफी मुश्किल होगा। –

6

चाहे promise.resolve() सिंक्रनाइज़ हो या असीमित रूप से इसकी निरंतरता निष्पादित करे, वास्तव में कार्यान्वयन पर निर्भर करता है।

इसके अलावा, "इवेंट लूप" एक अलग "निष्पादन संदर्भ" प्रदान करने वाला एकमात्र तंत्र नहीं है। अन्य साधन हो सकते हैं, उदाहरण के लिए धागे या थ्रेड पूल, या जीसीडी (ग्रांड सेंट्रल डिस्पैच, प्रेषण lib) के बारे में सोचें, जो प्रेषण कतार प्रदान करता है।

The Promises/A+ Spec स्पष्ट रूप से की आवश्यकता है कि निरंतरता (onFulfilled क्रमशः onRejected हैंडलर) हो जाएगा एसिंक्रोनस रूप "निष्पादन संदर्भ" जहां then विधि शुरू हो जाती है के संबंध में फांसी दे दी।

  1. onFulfilled या onRejected तक निष्पादन संदर्भ ढेर केवल मंच कोड शामिल नहीं कहा जाना चाहिए। [3.1]।

नोट्स के तहत आप पढ़ सकते हैं कि क्या वास्तव में मतलब है:

यहाँ "मंच कोड" इंजन, पर्यावरण, और वादा कार्यान्वयन कोड का मतलब है। व्यावहारिक रूप से, यह आवश्यकता सुनिश्चित करती है कि पूर्ण और ऑन-इंजेक्शन निष्पादित रूप से निष्पादित हो जाए, ईवेंट लूप बारी के बाद जिसे फिर कहा जाता है, और एक ताजा ढेर के साथ।

यहाँ, प्रत्येक घटना एक अलग "निष्पादन संदर्भ" पर निष्पादित किया जाएगा, भले ही यह एक ही घटना पाश है, और एक ही "सूत्र"।

के बाद से वादे/ए + विनिर्देश जावास्क्रिप्ट पर्यावरण के लिए लिखा है, एक अधिक सामान्य विनिर्देश बस की आवश्यकता होगी कि निरंतरता हो जाएगा एसिंक्रोनस रूप फोन करने वाले then विधि लागू करने के लिए सम्मान के साथ फांसी दे दी।

इस तरह से इसके अच्छे कारण हैं!

उदाहरण (छद्म कोड):

promise = async_task(); 
printf("a"); 
promise.then((int result){ 
    printf("b"); 
}); 
printf("c"); 

मानते हुए, हैंडलर (निरंतरता) कॉल-साइट के समान धागे पर निष्पादित करेंगे, निष्पादन के आदेश होना चाहिए कि सांत्वना यह दिखाता है:

acb 

विशेष रूप से, जब एक वादा पहले से ही हल हो गई है, कुछ कार्यान्वयन निरंतरता "तत्काल" (कि तुल्यकालिक है) एक ही निष्पादन संदर्भ पर आह्वान करने के लिए करते हैं। यह स्पष्ट रूप से ऊपर वर्णित नियम का उल्लंघन करेगा।

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

अन्य भाषाओं में कार्यान्वयन के लिए एक और खराब डिजाइन विकल्प जिसमें एकाधिक एक साथ निष्पादन संदर्भ होते हैं - एक बहु थ्रेडेड वातावरण (जावास्क्रिप्ट में अप्रासंगिक, क्योंकि निष्पादन का केवल एक धागा है) कहता है कि निरंतरता सिंक्रनाइज़ेशन की जाएगीresolve फ़ंक्शन के संबंध में। यह भी समस्याग्रस्त है जब एसिंक्रोनस कार्य बाद के ईवेंट लूप चक्र में समाप्त हो जाएगा और इस प्रकार निरंतरता को कॉल-साइट के संबंध में असीमित रूप से निष्पादित किया जाएगा।

हालांकि, जब resolve समारोह अतुल्यकालिक कार्य जब यह समाप्त हो गया है द्वारा सक्रिय किया जाएगा, इस काम के लिए एक निजी निष्पादन संदर्भ पर निष्पादित कर सकते हैं ("कार्यकर्ता सूत्र" कहते हैं)।यह "वर्कर थ्रेड" आमतौर पर समर्पित और संभवतः विशेष कॉन्फ़िगर किया गया निष्पादन संदर्भ - जो तब resolve पर कॉल करेगा। यदि resolve फ़ंक्शन सिंक्रनाइज़ निरंतरता निष्पादित करेगा, तो निरंतरता कार्य के निजी निष्पादन संदर्भ पर चलती है - जो आमतौर पर वांछित नहीं होती है।

संबंधित मुद्दे