2015-01-28 6 views
6

कई बार, मैं जावास्क्रिप्ट में इस तरह के एक आलसी अतुल्यकालिक लोड हो रहा है लिखने के लिए की जरूरत:इस async आलसी पैटर्न से कैसे बचें?

if (myvar != undefined){ 
    doSomeTreatment(myvar) 
} else { 
    loadMyVarAsynchronously().then(function(value){ 
     myvar = value 
     doSomeTreatment(myvar) 
    }) 
} 

यहाँ, myVar एक स्थानीय चर एक हैश के कुछ विशेषता, नहीं होगा। loadMyVarAsynchronously भार एसिंक्रोनस रूप से मूल्य myVar के लिए (के साथ उदाहरण के लिए, एक Promise या एक JQuery Deferred)

वहाँ एक पैटर्न में दो बार इस कोड में निम्न पंक्ति लिखने के लिए होने से बचाने के है?

var def = (myVar !== undefined) ? myVar : loadMyVarAsynchronously(); 

$.when(def).then(doSomeTreatment); 

काम myVar करने के लिए doSomeTreatment() अंदर, यदि आवश्यक हो, बनाने के बजाय अंदर:

doSomeTreatment(myvar) 
+0

उफ़ - इन jQuery का वादा कर रहे हैं या नए "मानक" वादे? – Alnitak

+0

मेरा प्रश्न अज्ञेयवादी होना चाहता था, ताकि उत्तर सबसे अच्छा समाधान प्रस्तावित कर सके! तो बस सर्वोत्तम मानक का उपयोग करें या वादा, या Deferred, या आप पसंद कुछ भी नहीं। –

उत्तर

1

यह क्या तुम यहाँ एक ठोस, वास्तविक दुनिया उदाहरण के बिना कर रहे हैं के बारे में कारण करने के लिए बहुत मुश्किल है। यह निश्चित रूप से एक पैटर्न नहीं है जिसका उपयोग मैं अपने कोड में बहुत अधिक उपयोग करता हूं, इसलिए मुझे संदेह है कि आप अपनी मान्यताओं का पुन: आकलन करके इसे ठीक करने के लिए जा सकते हैं।

कहा जा रहा है कि आप वादा श्रृंखला का उपयोग कर सकते हैं। इस मामले में नोट वादाThatLoadsVar एक वादा है, यह एक ऐसा काम नहीं है जो वादा करता है। इसका मतलब है कि यह एक राज्य को बनाए रखता है, और दूसरी बार यह कोड आगे बढ़ता है, यह तुरंत वापस आ जाएगा।

promisethatLoadsVar.then(function(value) { 
    myvar = value; 
    doSomeTreatment(myvar); 
}) 

आप एक स्पष्ट सवाल दे सकता है, तो मैं तुम्हारे लिए एक स्पष्ट उत्तर देने के लिए अच्छा लगेगा।

संपादित करें: मैं टिप्पणियों में उल्लिखित उदाहरण पर विस्तार करना चाहता हूं। LoDash लाइब्रेरी का उपयोग कर एक समाधान यहां दिया गया है। (बीटीडब्लू, आपको लॉनाश या अंडरस्कोर का उपयोग करना चाहिए, वे मूल रूप से जावास्क्रिप्ट की मानक लाइब्रेरी हैं)।

var getData = _.once(function() { return $.getJSON(...) }); 

$('button').on('click', function() { 
    getData().then(function(data) { showDialog(data) }) 
}) 

यहाँ ध्यान दें कि getData एक लिपटे समारोह है कि पहले मंगलाचरण के बाद सिर्फ समारोह को फिर से लागू बिना अधिक से अधिक एक ही बात वापस आ जाएगी है। पहली बार जब आप इसे आमंत्रित करेंगे, तो यह एक वादा वापस करेगा जो डेटा पुनर्प्राप्त होने पर हल हो जाता है। दूसरी बार आप वापस वही वादा प्राप्त करें जो पहले से ही हल हो जाएगा।

क्या आप getData पर पैरामीटर में पास करना चाहते हैं?

var getData = _.memoize(function(id) { return $.getJSON(url+id) }); 

$('button').on('click', function() { 
    getData($('#selector').val()).then(function(data) { showDialog(data) }) 
}) 

यह एक ही बात करते हैं, लेकिन पहले इनपुट पैरामीटर getData के लिए पारित द्वारा वादों को कैश होगा।

+1

मैं वास्तव में हैरान हूं कि आप मुझे बताएं कि यह एक उपयोगी पैटर्न नहीं है। बोनस में एसिंक्रोनस पैरामीटर के साथ, यह आलसी लोडिंग का एक बहुत ही शास्त्रीय तरीका है। यह, आईएमएचओ, प्रदर्शन की अवधि में और जीयूआई प्रतिक्रियाशीलता में एक बहुत अच्छा अनुकूलन है। –

+1

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

+0

मुझे इसके बारे में सोचने की ज़रूरत है। आप जो कहते हैं वह समझ में आता है। मुझे यह देखने की ज़रूरत है कि क्या मैं इस दृष्टि के अनुरूप विरासत कोड को अनुकूलित कर सकता हूं। आपके विचार को सटीक बनाने के लिए धन्यवाद। –

2

तो myvar पहले से ही आप $.when() में है कि पारित कर सकते हैं और यह अपने आप में एक संकल्प लिया वादा में लपेटा है परिभाषित किया गया है अज्ञात .then कॉलबैक, यह आपको फ़ंक्शन संदर्भ के रूप में सीधे doSomeTreatment पास करने की अनुमति देता है।

संपादित करें ओह, क्या आप मानक वादे, या jQuery वादे चाहते हैं? उपरोक्त jQuery शैली है।

+1

jQuery वादे मुझे रोते हैं। टीम [उन्हें बहुत गलत कैसे मिल सकती है] (https://blog.domenic.me/youre-missing-the-point-of-promises/)? – Sukima

+0

@ सुकिमा क्योंकि उन्होंने ए + से पहले एपीआई को मानकीकृत किया था, जो मुझे विश्वास है। –

+0

@ जॉर्ज मॉयर मुझे यकीन नहीं है कि यह पहले था, लेकिन मुझे विश्वास है कि jQuery ने वादा-_like_ एपीआई को अपनाने के लिए अवधारणा को बढ़ावा देने का एक लंबा सफर तय किया है। – Alnitak

1

हां, आपको मूल्य के लिए एक वादा बनाना चाहिए। तो फिर तुम बस केवल एक बार है कि समारोह संलग्न करने के लिए एक हैंडलर के रूप में की जरूरत है:

var loadedMyVar = myvar!=undefined ? Promise.resolve(myvar) : loadMyVarAsynchronously(); 
loadedMyVar.then(doSomeTreatment); 

ओह, और तुम सिर्फ हर जगह loadedMyVar वादा का उपयोग एसिंक्रोनस myvar को पुन: असाइन करने की जरूरत नहीं होनी चाहिए। शायद का उपयोग

var loadedMyVar = loadedMyVar || loadMyVarAsynchronously(); 
loadedMyVar.then(function(value) { 
    return myvar = value; 
}).then(doSomeTreatment); 
+0

मुझे अपने मामले में माईवर को फिर से सौंपना होगा, क्योंकि मैं दो तरीकों से प्रतिक्रियाशील के साथ बाध्यकारी उपयोग कर रहा हूं, इसलिए मैं एसिंक्रोनस लोडिंग फ़ंक्शन –

+0

में पुन: असाइन करूंगा, ठीक है, बस सुनिश्चित करें कि गीलेर कॉल के लिए उस मान पर भरोसा न करें 'loadMyVarAsynchronously() ', बेहतर सीधे वादे – Bergi

+0

के लिए देखो यह समझ में आता है। इस चेतावनी के लिए धन्यवाद। –

1

myvar != undefined का उपयोग करने के लिए अपनी जांच के रूप में अपनी जांच के रूप में एक समस्या है, और यह है कि जब आप किसी अन्य को शुरू करते हैं तो प्रगति में पहले से ही एक पुनर्प्राप्ति हो सकती है। आप अनुरोध दो बार (या अधिक!) कर सकते हैं।

इससे बचने के लिए आप वादा पर पकड़ कर सकते हैं, myvar के लिए एक भविष्य मूल्य रूप में यह इलाज है, और सब पर myvar का उपयोग नहीं:

// assume myvarpromise is persisted somewhere longer than the 
// life of this function 
myvarpromise = myvarpromise || loadMyVarAsynchronously(); 
myvarpromise.then(doSomeTreatment); 
+0

मुझे इसके बारे में कोई संदेह था: एक वादा पर विचार करें जिसे पहले ही हल कर लिया गया है। इसे कॉलबैक देना (तब कॉल के साथ (...)) इसे तुरंत कॉल करेंगे। –

+0

@ रेमीडुलेहे जब '.then()' को एक वादे पर बुलाया जाता है जिसे पहले से ही हल कर दिया गया है, तो हैंडलर को वादा/ए + -संगत वादे, और तुरंत jQuery वादे और कुछ अन्य प्रकार के वादों पर असीमित रूप से बुलाया जाएगा। – JLRishe

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