2009-11-27 20 views
19

में नोडजेस में बहुत सारे कॉलबैक रिकर्सन का प्रबंधन, वस्तुतः कोई अवरुद्ध I/O संचालन नहीं है। इसका मतलब है कि लगभग सभी नोडज आईओ कोड में कई कॉलबैक शामिल हैं। यह पढ़ने के लिए लागू होता है और लिखने के लिए/डेटाबेस, फ़ाइलें, प्रक्रियाओं, आदि इस का एक विशिष्ट उदाहरण से निम्नलिखित है:नोडज

var useFile = function(filename,callback){ 
    posix.stat(filename).addCallback(function (stats) { 
     posix.open(filename, process.O_RDONLY, 0666).addCallback(function (fd) { 
      posix.read(fd, stats.size, 0).addCallback(function(contents){ 
       callback(contents); 
      }); 
     }); 
    }); 
}; 

... 

useFile("test.data",function(data){ 
    // use data.. 
}); 

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

क्या मैं प्रभाव को गलतफहमी या कम करके समझ रहा हूं? यदि नहीं, तो क्या अभी भी नोडज की कॉलबैक कोडिंग शैली का उपयोग करते हुए इसे पाने का कोई तरीका है?

+0

विषय पुराना है लेकिन async: https://github.com/caolan/async – fider

उत्तर

24

आपके द्वारा दिखाए गए कोड में से कोई भी रिकर्सन का उपयोग नहीं कर रहा है। जब आप useFile पर कॉल करते हैं तो यह posix.stat() पर कॉल करता है, जो लौटाता है, और useFile समाप्त होने के बाद समाप्त हो जाता है। कुछ समय बाद, जब posix.stat() पर कॉल को अंतर्निहित सिस्टम के भीतर पूरा कर लिया है और परिणाम उपलब्ध हैं, तो आपके द्वारा जोड़े गए कॉलबैक फ़ंक्शन को निष्पादित किया जाएगा। वह posix.open() पर कॉल करता है, और उसके बाद समाप्त हो जाता है क्योंकि यह पूरा होने के लिए चलाया जाता है। एक बार फ़ाइल सफलतापूर्वक खोला जाने के बाद, के लिए कॉलबैक फ़ंक्शन निष्पादित करेगा, posix.read() पर कॉल करेगा, और फिर समाप्त हो जाएगा, क्योंकि यह भी पूरा होने के लिए चला गया है। अंत में, जब पढ़ने के परिणाम उपलब्ध होते हैं, तो सबसे निचला कार्य निष्पादित किया जाएगा। जो है, वे तुरंत कुछ जादू अंतर्निहित प्रणाली में शुरू किए जाने की वजह से हो रही है लौटने के लिए,:

महत्वपूर्ण मुद्दा यह है कि प्रत्येक कार्य, पूरा होने से चलाता है posix.*() कार्यों के लिए कॉल के रूप में गैर अवरुद्ध हो रहा है। तो आपके प्रत्येक कार्य समाप्त हो जाते हैं, और बाद में एक ईवेंट अगले कार्य को निष्पादित करने का कारण बनता है; लेकिन किसी भी समय कोई रिकर्सन नहीं है।

कोड की नेस्टेड संरचना एक इंप्रेशन दे सकती है कि अंदर की चीजें खत्म होने से पहले सामान को अपने अंतिम बिंदु तक पहुंचने से पहले खत्म करना होगा। लेकिन एसिंक्रोनस इवेंट-संचालित प्रोग्रामिंग की इस शैली में गहरी => होता है-बाद में के मामले में घोंसले को देखने में अधिक समझदारी होती है।

संपादित करें: प्रत्येक नेस्टेड फ़ंक्शन के अंत से पहले कुछ लॉगिंग स्टेटमेंट जोड़ने का प्रयास करें; इससे यह स्पष्ट करने में मदद मिलेगी कि जिस क्रम में वे पूरा करते हैं वह बाहरी अंदर से है।

+0

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

0

किसी भी जावास्क्रिप्ट के साथ, Node.js. के साथ रिकर्सिव कॉल करना संभव है। यदि आप रिकर्सन गहराई की समस्याओं में भाग लेते हैं (जैसे निकफिट्स बताते हैं, तो आप इसके खतरे में नहीं लगते हैं), आप अक्सर अपने कोड को अंतराल टाइमर का उपयोग करने के लिए फिर से लिख सकते हैं।

1

आपकी सामग्री ठीक है। मैं एक्सप्रेस में पुनरावर्ती कॉल HTTP अंतरण पालन करने के लिए करते हैं, लेकिन क्या अपने कर "ट्रेवर्सल" और

3

एक ही उदाहरण प्रत्यावर्तन नहीं, डिबग आउटपुट जोड़ा साथ (उत्पादन के लिए नीचे देखें):

usefile।js:

var sys = require("sys"), 
    posix = require("posix"); 

var useFile = function(filename,callback){ 
    posix.stat(filename).addCallback(function (stats) { 
     posix.open(filename, process.O_RDONLY, 0666).addCallback(function (fd) { 
      posix.read(fd, stats.size, 0).addCallback(function(contents){ 
       callback(contents); 
       sys.debug("useFile callback returned"); 
      }); 
      sys.debug("read returned"); 
     }); 
     sys.debug("open returned"); 
    }); 
    sys.debug("stat returned"); 
}; 

useFile("usefile.js",function(){}); 

आउटपुट:

DEBUG: stat returned 
DEBUG: open returned 
DEBUG: read returned 
DEBUG: useFile callback returned 
3

आप

http://github.com/creationix/do

कोशिश या अपने खुद के रोल की तरह मैंने किया जा सकता है। कभी अब के लिए से निपटने त्रुटि लापता मन (बस की अनदेखी है कि); इसे का उपयोग)

var sys = require('sys'); 

var Simplifier = exports.Simplifier = function() {} 

Simplifier.prototype.execute = function(context, functions, finalFunction) { 
    this.functions = functions; 
    this.results = {}; 
    this.finalFunction = finalFunction; 
    this.totalNumberOfCallbacks = 0 
    this.context = context; 
    var self = this; 

    functions.forEach(function(f) { 
    f(function() { 
     self.totalNumberOfCallbacks = self.totalNumberOfCallbacks + 1; 
     self.results[f] = Array.prototype.slice.call(arguments, 0);  
     if(self.totalNumberOfCallbacks >= self.functions.length) { 
     // Order the results by the calling order of the functions 
     var finalResults = []; 
     self.functions.forEach(function(f) { 
      finalResults.push(self.results[f][0]); 
     }) 
     // Call the final function passing back all the collected results in the right order 
     finalFunction.apply(self.context, finalResults); 
     } 
    }); 
    }); 
} 

और एक सरल उदाहरण

// Execute 
new simplifier.Simplifier().execute(
    // Context of execution 
    self, 
    // Array of processes to execute before doing final handling 
    [function(callback) { 
     db.collection('githubusers', function(err, collection) { 
     collection.find({}, {limit:30}, function(err, cursor) { 
      cursor.toArray(function(err, users) { callback(users); }) 
     }); 
     });  
    }, 

    function(callback) { 
     db.collection('githubprojects', function(err, collection) { 
     collection.find({}, {limit:45, sort:[['watchers', -1]]}, function(err, cursor) { 
      cursor.toArray(function(err, projects) { callback(projects); }) 
     }); 
     });    
    } 
    ], 
    // Handle the final result 
    function(users, projects) { 
    // Do something when ready 
    } 
); 
1

इसके अलावा 'कदम' (http://github.com/creationix/step) या 'प्रवाह js पर एक नज़र 'जिथब पर। यह आपको अधिक प्राकृतिक शैली में कॉलबैक प्रवाह लिखने देता है। यह यह भी स्पष्ट करेगा कि कोई रिकर्सन नहीं चल रहा है।

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