2016-01-10 10 views
6

भाषा: जावास्क्रिप्टजावास्क्रिप्ट: वादे के साथ रिकर्सिव कार्य कॉलिंग


Recursion - मेरी पसंदीदा विषय।

वादे - वे भ्रमित हो सकते हैं।

रिकर्सन + वादे - मुझे एक गद्देदार कमरे में प्रोग्राम करने की आवश्यकता है।

मैंने इस छोटी जेएस पहेली पहेली को The RecursiveFunHouse पर कॉल किया है, जो इस मूर्खता को कुछ मूर्खतापूर्ण तरीके से सरल बनाकर मेरी स्वच्छता को बनाए रखने के कॉमेडिक तरीके के रूप में है। उम्मीद है कि yall मेरे दर्द :) के बाहर एक हंसी प्राप्त कर सकते हैं

समस्या:

प्रत्येक पुनरावर्ती कॉल पिछले कॉल के परिणाम पर निर्भर है, लेकिन आदेश परिणाम मैं एक अतुल्यकालिक चलाना चाहिए प्राप्त करने के लिए कार्य और अन्य उप कार्यों में परिणाम का उपयोग करें।

"रिकर्सिव फ़न हाउस" ने मुझे इस मुद्दे को उबालने में मदद की - मूल रिकर्सिव लूप एक अनिर्धारित मान के साथ जारी है क्योंकि उप कार्य अभी भी निष्पादित हैं।

मज़ा हाउस - चारों ओर के बीच (-99) और 99 बार पिछले संख्या और नए नंबर के बीच पिछले अंतर यादृच्छिक संख्या का संग्रह छोरों सकारात्मक मज़ा

मुद्रण "पर इसे यहाँ बनाया गया 1 है ... इसे यहां बनाया 6 "यह इंगित करना चाहिए कि उप-कार्यों को सही तरीके से संभाला गया था और हमारे पास अगले लूप के लिए एक मूल्य है।

वर्तमान में यह 1,2,3,6,4,5 :(

recursiveFunHouse.js प्रिंट

var recursiveFunHouse = function(num){ 
    console.log("Made it here 1"); 
    var newNum = performSideTasks(); 

    console.log("Made it here 6"); 
    console.log("newNum"); 
    console.log(newNum); 
    if(newNum-num >0){ 
      recursiveFunHouse(newNum); 
    } 
    else{ 
     console.log("The FunHouse Generated These Numbers :") 
     for(var i = 0; i <numList.length; i++){ 
     console.log(numList[i]); 
     } 
    } 

}; 

var performSideTasks = function(){ 
    console.log("Made it here 2"); 
    someAsyncTask().then(function(num){ 
      anotherTask(num); 
     console.log("made it here 5"); 
     return num; 
     }); 


} 

var someAsyncTask = function(){ 
    return new Promise (function(resolve, reject) { 
    console.log("made it here 3"); 
    var randNum = Math.floor(Math.random()*99) + 1; 
    randNum *= Math.floor(Math.random()*2) == 1 ? 1 : -1; 

    setTimeout(function() { 
     numList.push(randNum) 
     resolve(randNum) 
    }, 100); 
    }); 
} 




var anotherTask = function(num){ 
    console.log("made it here 4"); 
    console.log(num); 

}; 

var numList= []; 

recursiveFunHouse(20); 

नोट - मेरी दयनीय वापसी कथन return num; माफ कर दो यह सिर्फ मैं क्या इच्छा से पता चलता मैं अपने कंप्यूटर बता सकते

Recursion बारे में प्रश्न और वादे:।

1) क्या मुझे अगली रिकर्सिव लूप में जाने के बारे में पहली जगह में चिंतित होना चाहिए, जो अभी तक हल नहीं हुआ है?

2) यदि नहीं, तो इस कार्य को अपघटन रखने और अंतिम रिकॉर्डेड लूप को अंतिम कॉल के समाधान की प्रतीक्षा करने के लिए एक साफ तरीका क्या है?


Recursion और वादे जादूगर स्तरीय -95 जादुई कभी कभी ... कि सभी मैं कह रहा हूँ लग सकता है। प्रश्न-हो गया।

+0

performSideTasks someAsynTask वादा ही लौटना चाहिए, ताकि मुख्य कार्य तो फिर() – Supersharp

उत्तर

5

के रूप में टिप्पणी में कहा गया है, तो आप इसे वादा वापसी बनाने के लिए थोड़ा performSideTasks संशोधित करने के लिए है:

var performSideTasks = function() 
{ 
    console.log("Made it here 2") 
    return someAsyncTask().then(function (num) 
    { 
    anotherTask(num); 
    console.log("made it here 5") 
    return num 
    }) 
} 

तो फिर तुम मुख्य कार्य के then() विधि में अतुल्यकालिक परिणाम का उपयोग कर सकते हैं।

var recursiveFunHouse = function (num) 
{ 
    console.log("Made it here 1") 
    performSideTasks().then(function (newNum) 
    { 
    console.log("Made it here 6") 
    console.log("newNum") 
    console.log(newNum) 
    if (newNum-num > 0) 
    { 
     recursiveFunHouse(newNum) 
    } 
    else 
    { 
     console.log("The FunHouse Generated These Numbers :") 
     for(var i = 0 ; i <numList.length ; i++) 
     { 
     console.log(numList[i]) 
     } 
    } 
    }) 
} 
+1

Thx @Supersharp अंदर संख्या मूल्य प्राप्त कर सकते हैं! –

+2

@Supersharp: मैंने देखा है कि मैंने देखा है कि अधिकांश कोड में एक अलग [इंडेंट शैली] (https://en.wikipedia.org/wiki/Indent_style) का उपयोग करें। यह जरूरी नहीं है कि एक बुरी चीज है, लेकिन बस अपनी चुनी शैली से सावधान रहें - जावास्क्रिप्ट में [स्वचालित अर्धविराम सम्मिलन] (http://bonsaiden.github.io/JavaScript-Garden/#core.semicolon) के कारण, इसका कारण हो सकता है आप अप्रत्याशित बग – GregL

10

शास्त्रीय तुल्यकालिक प्रत्यावर्तन में, प्रत्यावर्तन राज्य धक्का दिया ढेर फ्रेम में जमा हो जाती है और एक आम निष्पादन ढेर बंद पॉप है। एसिंक्रोनस रिकर्सन में, रिकर्सन स्टेटस को वादा किए गए वादे ऑब्जेक्ट्स में संग्रहीत किया जा सकता है और एक आम वादा श्रृंखला से पॉप आउट हो जाता है। उदाहरण के लिए:

function asyncThing(asyncParam) // something async returning a promise 
{ return new Promise(function(resolve, reject) 
    { function timeOut() 
     { resolve(asyncParam); // resolve with parameter value passed 
     } 
     setTimeout(timeOut, 1000); 
    }); 
} 
function recFun(num) // asynchronous recursive function 
{ 
    // do whatever synchronous stuff when called 
    // ... 
    function decide(asyncResult) // process async result and decide what to do 
    { // do something with asyncResult 
     console.log("asyncResult: " + asyncResult); 
     if(asyncResult == 0) 
      console.log("ignition"); 
     // decide if further recursion needed 
     if(asyncResult < 0) 
      return "lift off"; // all done 
     return recFun(num-1); // not all done, recurse 
    } 

    // return a promise resolved by doing something async and deciding what to do with it 
    // to be clear the returned promise is the one returned by .then 
    return asyncThing(num).then(decide); 
} 

// call the recursive function 

recFun(5) 
.then(function(result) {console.log("done, result = " + result); }) 
.catch(function(err) {console.log("oops:" + err);}); 

इसके प्रभाव को देखने के लिए कोड चलाएं।

कोर सिद्धांतों (जादू) है जिस पर इस उदाहरण निर्भर करता है:

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

    अगर और श्रोता कार्यों को निष्पादित किया जाता है (क्योंकि एक वादा पूरा हो जाता है या खारिज कर दिया जाता है) उन्हें ईवेंट लूप से बाहर अपने कॉल में अतुल्यकालिक रूप से निष्पादित किया जाता है, जिसके परिणामस्वरूप श्रोता निष्पादित किया जा रहा है जिसके परिणामस्वरूप स्वयं पूरा हो जाता है।

    यह सभी लॉग जब वादा श्रोताओं को पंजीकृत (then फोन करके) की गई प्रविष्टियों से पहले किसी भी लॉग जब एसिंक्रोनस रूप से निष्पादित एक श्रोता समारोह में की गई, कुछ समय बाद प्रविष्टि दिखाई देती हैं। वादे में समय यात्रा शामिल नहीं है।

क्या यह आपके सिर को चोट पहुंचाने से रोक देगा? शायद नहीं, लेकिन कम से कम यह सच है।

`

+0

व्यापक, प्रबुद्ध स्पष्टीकरण और उदाहरण! – Velojet

+0

ग्रेट स्पष्टीकरण। मैं जावास्क्रिप्ट में इसी तरह जोड़ूंगा, बस 'थ्रेड' को 'ईवेंट लूप की बारी' के साथ प्रतिस्थापित करें –

+0

@DeanRadcliffe अच्छा बिंदु। यह जावास्क्रिप्ट उत्तर है लेकिन इवेंट लूप से कॉल आउट करने के लिए "थ्रेड" का मेरा उपयोग गलत था। भ्रम के स्रोत को हटाने के लिए अद्यतन उत्तर। टिप्पणी के लिए धन्यवाद। – traktor53

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