Angularjs $ q.all


106

मैंने angularjs में $ q.all लागू किया है, लेकिन मैं कोड का काम नहीं कर सकता। यहाँ मेरा कोड है:

UploadService.uploadQuestion = function(questions){

        var promises = [];

        for(var i = 0 ; i < questions.length ; i++){

            var deffered  = $q.defer();
            var question  = questions[i]; 

            $http({

                url   : 'upload/question',
                method: 'POST',
                data  : question
            }).
            success(function(data){
                deffered.resolve(data);
            }).
            error(function(error){
                deffered.reject();
            });

            promises.push(deffered.promise);
        }

        return $q.all(promises);
    }

और यहाँ मेरा नियंत्रक है जो सेवाओं को कॉल करता है:

uploadService.uploadQuestion(questions).then(function(datas){

   //the datas can not be retrieved although the server has responded    
}, 
function(errors){ 
   //errors can not be retrieved also

})

मुझे लगता है कि मेरी सेवा में $ q.all स्थापित करने में कुछ समस्या है।


1
आप क्या व्यवहार देख रहे हैं? क्या यह आपके अंदर बुलाता है then(datas)? इसे बस करने का प्रयास pushकरें:promises.push(deffered);
डेविन ट्रेटन

@ themyth92 क्या आपने मेरे समाधान की कोशिश की है?
इलन फ्रुमर

मैंने कोशिश की है और दोनों विधि मेरे मामले पर काम करती है। लेकिन मैं सही उत्तर के रूप में @Llan Frumer बनाऊंगा। वास्तव में आप दोनों को धन्यवाद।
उनहैत92

1
आप मौजूदा वादे का वादा क्यों कर रहे हैं? $ http पहले से ही एक वादा लौटाता है। $ Q.defer का उपयोग बहुत ही शानदार है।
पीट एल्विन

1
यह deferredनहीं है deffered:)
क्रिस्टोफ़ Roussy

जवाबों:


225

जावास्क्रिप्ट में block-level scopesकेवल वही नहीं हैंfunction-level scopes :

इस लेख को javaScript स्कोपिंग और होस्टिंग के बारे में पढ़ें

देखें कि मैंने आपका कोड कैसे डीबग किया:

var deferred = $q.defer();
deferred.count = i;

console.log(deferred.count); // 0,1,2,3,4,5 --< all deferred objects

// some code

.success(function(data){
   console.log(deferred.count); // 5,5,5,5,5,5 --< only the last deferred object
   deferred.resolve(data);
})
  • जब आप var deferred= $q.defer();लूप के लिए लिखते हैं तो यह फ़ंक्शन के शीर्ष पर फहराया जाता है, इसका मतलब है कि जावास्क्रिप्ट इस चर को फ़ंक्शन के दायरे से बाहर घोषित करता है for loop
  • प्रत्येक लूप के साथ, पिछले आस्थगित पिछले एक को ओवरराइड कर रहा है, उस ऑब्जेक्ट के संदर्भ को बचाने के लिए कोई ब्लॉक-स्तरीय गुंजाइश नहीं है।
  • जब एसिंक्रोनस कॉलबैक (सफलता / त्रुटि) का आह्वान किया जाता है, तो वे केवल अंतिम आस्थगित वस्तु को संदर्भित करते हैं और केवल इसे हल किया जाता है, इसलिए $ q.all को कभी हल नहीं किया जाता है क्योंकि यह अभी भी अन्य आस्थगित वस्तुओं की प्रतीक्षा करता है।
  • आपको प्रत्येक आइटम के लिए एक अनाम फ़ंक्शन बनाने की आवश्यकता है जो आप इसे पुनरावृत्त करते हैं।
  • चूंकि फ़ंक्शंस में स्कोप होते हैं, इसलिए फ़ंक्शंस closure scopeनिष्पादित होने के बाद भी आस्थगित ऑब्जेक्ट्स के संदर्भ को संरक्षित किया जाता है।
  • जैसा कि #dfsq ने टिप्पणी की: $ http से एक वादा वापस करने के बाद से मैन्युअल रूप से एक नई आस्थगित वस्तु का निर्माण करने की आवश्यकता नहीं है।

के साथ समाधान angular.forEach:

यहाँ एक डेमो प्लंकर है: http://plnkr.co/edit/NGMp4ycmaCqVOmgohN53?p=preview

UploadService.uploadQuestion = function(questions){

    var promises = [];

    angular.forEach(questions , function(question) {

        var promise = $http({
            url   : 'upload/question',
            method: 'POST',
            data  : question
        });

        promises.push(promise);

    });

    return $q.all(promises);
}

मेरा पसंदीदा तरीका उपयोग करना है Array#map:

यहाँ एक डेमो प्लंकर है: http://plnkr.co/edit/KYeTWUyxJR4mlU77svw9?p=preview

UploadService.uploadQuestion = function(questions){

    var promises = questions.map(function(question) {

        return $http({
            url   : 'upload/question',
            method: 'POST',
            data  : question
        });

    });

    return $q.all(promises);
}

14
अच्छा उत्तर। एक जोड़: $ http से प्रतिफल के बाद से नए आस्थगित के निर्माण की आवश्यकता नहीं है। तो यह छोटा हो सकता है: plnkr.co/edit/V3gh7Roez8WWl4NKKrqM?p=preview
dfsq

"जब आप var deferred = $ q.defer () लिखते हैं, तो लूप के अंदर यह फ़ंक्शन के शीर्ष पर फहराया जाता है।" मैं इस हिस्से को नहीं समझता, क्या आप इसके पीछे का कारण बता सकते हैं?
उनहैत92

मुझे पता है, मैं वास्तव में ऐसा ही करूंगा।
dfsq

4
mapवादों की एक सरणी बनाने के लिए उपयोग से प्यार करें । बहुत ही सरल और संक्षिप्त।
Drumbeg

1
यह ध्यान दिया जाना चाहिए कि घोषणा को फहराया गया है, लेकिन असाइनमेंट जहां है वहीं रहता है। इसके अलावा, अब 'लेट' स्टेटमेंट के साथ ब्लॉक-स्तरीय स्कूपिंग है। देखें developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
स्पेंसर

36

$ http एक वादा भी है, आप इसे सरल बना सकते हैं:

return $q.all(tasks.map(function(d){
        return $http.post('upload/tasks',d).then(someProcessCallback, onErrorCallback);
    }));

2
हां, स्वीकृत उत्तर केवल विरोधी प्रतिरूपों का एक समूह है।
Roamer-1888

मुझे लगता है कि आप .then()खंड को छोड़ सकते हैं क्योंकि ओपी अपने नियंत्रक में वह सब करना चाहता है, लेकिन सिद्धांत पूरी तरह से सही है।
Roamer-1888

2
बेशक आप तत्कालीन क्लॉज को छोड़ सकते हैं, मैंने इसे सभी HTTP अनुरोधों को लॉग इन करने के मामले में जोड़ा, मैं हमेशा उन्हें जोड़ता हूं और सभी सर्वर अपवादों को संभालने के लिए एक वैश्विक ऑनरॉयर कॉलबैक का उपयोग करता हूं।
ज़ेरकोटिन

1
आप कर सकते हैं @Zerkotin throwएक से .thenदोनों संभाल इसे बाद में करने के लिए और यह करने के लिए बेनकाब $exceptionHandler, जो आपको लगता है कि मुसीबत और एक वैश्विक बचाने चाहिए।
बेंजामिन ग्रुएनबाम

अच्छा लगा। यह अनिवार्य रूप से स्वीकृत उत्तर के अंतिम समाधान / उदाहरण के समान दृष्टिकोण है।
निको बेलिक

12

मुद्दा यह लगता है कि आप deffered.promiseकब जोड़ रहे हैंdeffered खुद वादा है चाहिए:

बदलने की कोशिश करो promises.push(deffered);ताकि आप सरणी में अलिखित वादा न जोड़ें।

 UploadService.uploadQuestion = function(questions){

            var promises = [];

            for(var i = 0 ; i < questions.length ; i++){

                var deffered  = $q.defer();
                var question  = questions[i]; 

                $http({

                    url   : 'upload/question',
                    method: 'POST',
                    data  : question
                }).
                success(function(data){
                    deffered.resolve(data);
                }).
                error(function(error){
                    deffered.reject();
                });

                promises.push(deffered);
            }

            return $q.all(promises);
        }

यह केवल खराब वस्तुओं की एक सरणी देता है, मैंने इसे चेक किया।
इलन फ्रुमर

मुझे नहीं पता कि वह क्या कहता है, केवल सांत्वना क्या कहती है, आप देख सकते हैं कि यह काम नहीं कर रहा है: plnkr.co/edit/J1ErNncNsclf3aU86D7Z?p=preview
इलन फ्रूमन

4
इसके अलावा प्रलेखन स्पष्ट रूप से कहता है कि $q.allवादे किए गए वस्तुओं को स्थगित नहीं करता है। ओपी की असली समस्या
स्कूपिंग के

इलान, deferवस्तुओं को नापसंद करने के लिए धन्यवाद और promises। आपने मेरा all()मुद्दा भी ठीक कर दिया।
रॉस रोजर्स

समस्या को 2 उत्तरों में हल किया गया था, समस्या स्कूपिंग या परिवर्तनशील हो रही है, जिसे आप इसे कॉल करना चाहते हैं।
ज़ेरकोटिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.