2013-12-16 9 views
13

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

पुनरावर्ती क्रिया

loadSection2 = function() { 

    var apiURL = "http://..." 

    var deferred = $q.defer(); 

    $http({ 
     method: "GET", 
     url: apiURL 
    }).success(function(result, status, headers, config) { 
     console.log(result); 
     loadCount++; 
     if(loadCount < 10) { 
      newSectionArray.push(result); 
      loadSection2(); 
     } else { 
      loadCount = 0; 
      deferred.resolve(); 
      return deferred.promise; 
     } 
    }).error(function() { 
     return deferred.reject(); 
    }); 
    deferred.notify(); 
    return deferred.promise; 
}; 

तो

loadSection2().then(function() { 
    console.log("NEW SECTIONS LOADED, start adding to document"); 
    addContent(); 
}, function() { 
    console.log("ERROR CALLBACK"); 
}, function() { 
    console.log("NOTIFY CALLBACK"); 
}).then(function() { 
    loadScrollActive = false; 
}); 

मुझे लगता है, तो कम से कम पहले सूचित-कॉलबैक प्राप्त करने के लिए है:

यहाँ मेरी कोड है। लेकिन कोई कॉलबैक नहीं है। फिर रिकर्सिव फ़ंक्शन के साथ काम नहीं कर रहा है?

+0

क्या आप हमें एक jsfiddle दे सकते हैं? – Manishearth

+1

एक चीज जो मैं देखता हूं वह यह है कि आप कॉलबैक फ़ंक्शन से कुछ वापस नहीं कर सकते हैं। तो .success में deferred.promise वापस करें और आतंक वास्तव में कुछ भी नहीं करता है। हालांकि समस्या का कारण नहीं है। – Narretz

+1

'loadCount' कहां परिभाषित किया गया है? और, 'सूचित करें' आपके जैसा काम नहीं करता है। मेरे पास कोणीय रेपो में एक खुली समस्या है -> https://github.com/angular/angular.js/issues/5277 – Rifat

उत्तर

21

संपादित करें - 2015/11/11 यदि आप के बारे में परवाह नहीं है सूचित वहाँ एक अधिक स्वच्छ तरीका है:

loadSection2 = function(){ 
    var apiURL = "http://..." 
    return $http.get(apiURL) 
     .then(function(response){ 
      loadCount++;   
      if (loadCount < 10) { 
       newSectionArray.push(response.data); 
       return loadSection2(); 
      } 
      loadCount = 0; 
     }); 

}; 

पुराना जवाब यहाँ उपलब्ध है:

आप लगातार गुजारें सकता वादे के माध्यम से सभी तरह से।

loadSection2 = function(deferred) { 

    if(!deferred){ 
     deferred = $q.defer(); 
    } 
    var apiURL = "http://..." 

    $http({ 
     method: "GET", 
     url: apiURL 
    }).success(function(result, status, headers, config) { 
     console.log(result); 
     loadCount++; 
     if(loadCount < 10) { 
      newSectionArray.push(result); 
      loadSection2(deferred); 
     } else { 
      loadCount = 0; 
      deferred.resolve(); 
      return deferred.promise; 
     } 
    }).error(function() { 
     return deferred.reject(); 
    }); 
    deferred.notify(); 
    return deferred.promise; 
}; 
+1

मैथ्यू, मुझे लगता है कि आप वास्तव में अपने रिकर्सिव कॉल में 'स्थगित' पास करना भूल गए हैं, लेकिन यह सही जवाब है। आपकी समस्या यह है कि जब भी आप विधि को कॉल करते हैं, तो आप पूरी प्रक्रिया के लिए उसी का उपयोग करने के बजाय एक नया 'स्थगित' ऑब्जेक्ट बना रहे हैं। तो पहली बार जब आप loadSection2 कहते हैं, तो आपको 1 वापस स्थगित हो जाता है, लेकिन स्थगित होने वाला स्थगित वास्तव में स्थगित 10 है। स्थगित पास करने से मदद मिलेगी, या आप अपनी विधि के बाहर चर बना सकते हैं और इसे एक्सेस करने के लिए बंद कर सकते हैं। – Hylianpuffball

+0

आप पूरी तरह से सही हैं, मेरा मतलब है कि इसे पास करना है, संपादित करें उत्तर दें। –

+0

@MathewBerg कृपया मुझे "अन्यथा" ब्लॉक से "वापसी स्थगित वादे" के कारण को समझने में मदद करें। मैंने इस उदाहरण का एक क्यू संस्करण तैयार किया है जहां अन्य ब्लॉक में मैं deferred.promise वापस नहीं कर रहा हूं; और यह ठीक काम करता है। [लिंक] (https://gist.github.com/pulakb/94d9d1c96e77537c304e) –

0

Fauphi,

Recursion पूरी तरह से व्यवहार्य नहीं बल्कि एक विशेष रूप से "promisy" दृष्टिकोण है।

यह देखते हुए कि आपके पास स्थगित/वादे उपलब्ध हैं, आप गतिशील रूप से .then() श्रृंखला बना सकते हैं, जो एक आबादी वाले सरणी का वादा प्रदान करता है।

function loadSection2(arr) { 
    return $http({ 
     method: "GET", 
     url: "http://..." 
    }).then(function(result, status, headers, config) { 
     console.log(result); 
     arr.push(result); 
     return arr;//make the array available to the next call to loadSection2(). 
    }, function() { 
     console.log("GET error"); 
     return $q.defer().resolve(arr).promise;//allow the chain to continue, despite the error. 
     //or I think $q's .then() allows the much simpler form ... 
     //return arr; //allow the chain to continue, despite the error. 
    }); 
}; 

var newSectionPromise = $q.defer().resolve([]).promise;//note that the deferred is resolved with an anonymous new array. 
//Now we build a .then() chain, ten long, ... 
for (var i=0; i<10; i++) { 
    newSectionPromise = newSectionPromise.then(loadSection2); 
} 
// ... and do something with the populated array when the GETs have done their thing. 
newSectionPromise().then(function(arr) { 
    console.log(arr.length + " new sections loaded, start adding to document"); 
    addContent(arr); 
}, function() { 
    console.log("ERROR CALLBACK"); 
}).then(function() { 
    loadScrollActive = false; 
}); 

अपरीक्षित

क्या newSectionArray अब गुमनाम रूप से बनाई गई है था और सफलता की परवाह किए बिना .then() श्रृंखला नीचे पारित कर दिया/व्यक्ति की विफलता हो जाता है, तो फिर अंतिम की सफलता हैंडलर में arr रूप में उभर रहा है, जहां यह addContent() पर पास किया गया है। यह बाहरी दायरे में सदस्य newSectionArray की आवश्यकता से बचाता है।

थोड़ा पीछे हटना, loadSection2 अज्ञात बना दिया जा सकता है, और बाहरी दायरे में जोड़े गए सदस्यों की संख्या को कम करता है।

एक स्पष्ट अधिसूचना के लिए की जरूरत गायब हो जाता है के रूप में:

  • वहाँ नहीं रह गया है एक मास्टर प्राप्त सफलता हैंडलर में
  • console.log(result); अधिसूचित किया जाना टाल सभी अधिसूचना आवश्यक प्रदान करता है।
3

मैं एक समाधान नहीं होता है कि "आस्थगित" चर के आसपास और यहां तक ​​कि मैं यह नहीं कहूंगा कि यह एक बेहतर तरीका है, यह काम करता है और मैं इसे (jsfiddle) से सीखा हालांकि बनाना चाहते थे।

1 9/अगस्त/14 - एफ 1() में एक और वादे के निर्माण को हटाकर कोड को बहुत कम संस्करण में अपडेट किया गया। मुझे उम्मीद है कि यह स्पष्ट है कि यह मूल प्रश्न से कैसे संबंधित है। अगर यह मुझे एक टिप्पणी में नहीं जाने देता है।

f1().then(function() { 
    console.log("done"); 
}); 

function f1(counter) { 

    if (!counter) { 
     counter = 0; 
    } 

    counter++; 
    console.log(counter); 

    return asyncFunc().then(function() { 
     if (counter < 10) { 
      return f1(counter); 
     } else { 
      return; 
     } 
    }); 

} 

function asyncFunc() { 
    var deferred = $q.defer(); 

    $timeout(function() { 
     deferred.resolve(); 
    }, 100); 

    return deferred.promise; 
} 
संबंधित मुद्दे