2013-11-21 18 views
5

मूल रूप से करने के लिए एक के अंदर कॉलबैक फ़ंक्शन लागू, मैं एक समारोह है, जहां एक पाश जो के अंदर चल रहा है कई कॉलबैक फ़ंक्शन वर्तमान (कॉलबैक नरक) कर रहे हैं कॉल करने के लिए कोशिश कर रहा हूँ .. के रूप में नीचे:NodeJS: पाश

for(var i=0;i<data.id.length;i++) 
{ 
    DAO.getUserById(data.id[i],function(err,resp1) 
    { 
     /* some other work based on resp1 */ 
     DAO.getOtherData(resp1.username,resp1.userId,function(err,resp2) 
     { 
      /* similary some other work*/ 
     }); 
    }); 
} 

मेरे पास मेरे ऐप में कई स्थानों पर एक ही पैटर्न है, और कुछ बार मुझे कॉलबैक के साथ समस्या का सामना करना पड़ा, कि लूप खत्म हो गया, लेकिन कॉलबैक प्रतिक्रिया नहीं देता है, ऐसा लगता है कि डीएओ विधि को कॉल किया गया है लेकिन अभी भी प्रतिक्रिया की प्रतीक्षा है। क्या इस मुद्दे को दूर करने के लिए कोई अनुकूलित तरीका है?

यह जानना अच्छा होगा अगर वहाँ कुछ जावास्क्रिप्ट कोडिंग पैटर्न उपलब्ध इस मुद्दे। (किसी भी 3 पार्टी पुस्तकालय के अलावा अन्य) धन्यवाद

उत्तर

3

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

लेकिन जब जो आपको अधिक पठनीय तरह से काम करता है श्रृंखला की तरह तो या अन्य सहायक कार्यों देखते हैं। Q या jQuery कार्यान्वयन को देखें। एक बहुत अच्छी शुरुआत के लिए Async जावास्क्रिप्ट पुस्तक पढ़ें।

संपादित करें:/

मैं तुम्हारे लिए js fiddle के रूप में एक छोटे से काम कर रहे उदाहरण था।

var data = { id : [] }; 

    for(var i = 0; i < 10; i++) { 
     data.id.push(i); 
    } 

    // DAO definition 
    var DAO = { 
     getUserById : function(id) { 
      var deferred = $.Deferred(); 

      setTimeout(function() { 
       var isError = Math.floor(Math.random()*11) > 5; 

       if(isError) { 
        deferred.reject("WOW - Much Handler - So error"); 
       } else { 
        deferred.resolve({ 
         username : 'Max', 
         userId : id 
        }); 
       } 
      }, 50); 

      return deferred.promise(); 
     }, 

     getOtherData : function(username, userId) { 
      var deferred = $.Deferred(); 

      setTimeout(function() { 
       deferred.resolve((username + ' id: ' + userId)); 
      }, 20); 

      return deferred.promise(); 
     } 
    }; 



    function printResult(res) { 
     $('#result').html($('#result').html() + '<br />' + res); 
    }; 

    // DAO usage 

    for(var i=0;i<data.id.length;i++) 
    { 
     DAO.getUserById(data.id[i]) 
     .done(function(res) { 
      DAO.getOtherData(res.username, res.userId).done(function(result) { 
       printResult(result); 
      }); 
     }) 
     .fail(function(res) { 
      printResult(res); 
     }); 
    } 

कि का सबसे बड़ा फायदा दोहरा है:

  1. आप के लिए मुफ्त
  2. त्रुटि हैंडलर कोड और परिणाम हैंडलर कोड की जुदाई प्राप्त यह आप नेस्टिंग नरक से रोकता है। (कॉलबैक, कॉलबैक में, कॉलबैक में ...) स्थगित होने के कारण आप वास्तविक तर्क को वास्तविक बनाने में सक्षम हैं।
  3. कॉलबैक सिंक्रनाइज़ करना बहुत आसान हो जाता है क्योंकि आपको केवल when का उपयोग करने की आवश्यकता है।

मैंने jQuery का उपयोग किया क्योंकि jsfiddle में ड्रॉपडाउन बॉक्स में jquery है। आप जो भी कार्यान्वयन चाहते हैं उसका उपयोग कर सकते हैं।

जब आपको इसे लागू करने की अवधारणा मिल गई तो आपको बहुत कठिन नहीं होना चाहिए।

+0

* डिफर्ड या वादे * मैंने उनके बारे में सुना लेकिन मैं अपने कोड के साथ कार्यान्वित करना संभव नहीं कर सका। क्या कोई अच्छा संसाधन/ईबुक उपलब्ध है जिसका उपयोग करके मैं अपनी समस्या का समाधान कर सकता हूं? – agpt

+0

@Aman पुस्तक Async जावास्क्रिप्ट। यह पॉल द्वारा उल्लिखित जलप्रपात के बारे में भी बात करता है। आप अपने डीएओ कार्यों को वास्तविक रिटर्न वादे के लिए फिर से लिख सकते हैं और अपने हैंडलर को उनके साथ संलग्न कर सकते हैं। तो आप इस बुरा घोंसले से बच सकते हैं। – schlingel

+0

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

2

आप async.waterfall function का उपयोग कर सकते हैं जो वास्तव में आपके मुद्दे से निपटने के लिए है। अगले कार्यों में पैरामीटर के रूप में भेजे गए फ़ंक्शन के परिणामस्वरूप, सभी कार्यों को श्रृंखला में कहा जाता है। दस्तावेज से नमूना उपयोग यहां दिया गया है:

async.waterfall([ 
    function(callback){ 
     callback(null, 'one', 'two'); 
    }, 
    function(arg1, arg2, callback){ 
     callback(null, 'three'); 
    }, 
    function(arg1, callback){ 
     // arg1 now equals 'three' 
     callback(null, 'done'); 
    } 
], function (err, result) { 
    // result now equals 'done'  
}); 
0

इस कोड को देखें।

var i=0; 
var length = data.id.length; 
var getData = function(index) 
{ 
    DAO.getUserById(data.id[index],function(err,resp1) 
    { 
     /* some other work based on resp1 */ 
     DAO.getOtherData(resp1.username,resp1.userId,function(err,resp2) 
     { 
      /* similary some other work*/ 
      index++; 
      if(index < length) 
      { 
       getData(index); 
      } 
     }); 
    }); 
} 
getData(i); 

क्या आपको इसकी आवश्यकता है?

+0

नहीं नहीं ... मैंने इसे पहले से ही कार्यान्वित कर दिया है, मूल रूप से मैं जानना चाहता हूं कि कॉलबैक क्यों लटका हुआ है? और नेस्टेड कॉलबैक से कैसे बचें। – agpt

+0

यह भयानक अपठनीय दिखता है। – schlingel

+0

@Gowsikan, आपको कैसे पता चलेगा कि 'getData (i)' पूरा हो गया है और कोई मान वापस आया है? बात यह है कि कुछ समय कॉलबैक आपको आवंटित कार्य या नोडजेस थ्रेड को प्राथमिकता के आधार पर तुरंत आउटपुट नहीं देता है (यदि मैं गलत नहीं हूं)। – agpt