क्या आप इसे वापस करने से पहले एक कोणीय वादे का समाधान कर सकते हैं?


125

मैं एक फ़ंक्शन लिखने का प्रयास कर रहा हूं जो एक वादा लौटाता है। लेकिन ऐसे समय होते हैं जब अनुरोधित जानकारी तुरंत उपलब्ध होती है। मैं इसे एक वादे में लपेटना चाहता हूं ताकि उपभोक्ता को निर्णय लेने की आवश्यकता न हो।

function getSomething(id) {
    if (Cache[id]) {
        var deferred = $q.defer();
        deferred.resolve(Cache[id]); // <-- Can I do this?
        return deferred.promise;
    } else {
        return $http.get('/someUrl', {id:id});
    }
}

और इसे इस तरह से उपयोग करें:

somethingService.getSomething(5).then(function(thing) {
    alert(thing);
});

समस्या यह है कि कॉलबैक पूर्व-हल किए गए वादे के लिए निष्पादित नहीं करता है। क्या यह एक वैध बात है? क्या इस स्थिति को संभालने का एक बेहतर तरीका है?


10
पहले मामले में रिटर्न लिखने का एक सरल तरीका है return $q.when(Cache[id])। किसी भी तरह, यह काम करना चाहिए और हर बार कॉलबैक करना चाहिए क्योंकि आप हर बार नए वादे कर रहे हैं।
मुशायरों में

3
कार्य करना: plnkr.co/edit/OGO8T2M1fE3Mrgj2oozj?p=preview
JB Nizet

1
Crud। मेरे जीवन का एक घंटा खो गया। मैं एक इकाई परीक्षण में यह कोशिश कर रहा था और परीक्षण पूरा होने के बाद वादा पूरा हुआ, और मैं इसे नहीं देख रहा था। मेरे परीक्षण के साथ समस्या है और कोड नहीं।
क्रेग सेलेस्टे

सुनिश्चित करें कि आप $ गुंजाइश कहते हैं। परीक्षण के दौरान सही चीजों को हल करने के लिए $ apply () लागू करें।
dtabuenc

मुझे लगता है कि इसके लिए httpbackend.flush खाता है लेकिन $ q नहीं हो सकता है। मैं इस परीक्षण में गुंजाइश का उपयोग नहीं कर रहा हूँ। मैं सीधे सेवा का परीक्षण कर रहा हूं, लेकिन मुझे यह काम करने के लिए मिला, धन्यवाद।
क्रेग सेलेस्टे

जवाबों:


174

संक्षिप्त उत्तर: हां, आप इसे वापस करने से पहले एक AngularJS वादे को हल कर सकते हैं, और यह वैसा ही व्यवहार करेगा जैसा आप अपेक्षा करते हैं।

से जेबी Nizet के Plunkr लेकिन और वास्तव में साइट पर क्या मूल रूप से कहा गया था के संदर्भ में काम करने के लिए पुनर्संशोधित (सेवा करने के लिए यानी एक समारोह कॉल)।

सेवा के अंदर ...

function getSomething(id) {
    // There will always be a promise so always declare it.
    var deferred = $q.defer();
    if (Cache[id]) {
        // Resolve the deferred $q object before returning the promise
        deferred.resolve(Cache[id]); 
        return deferred.promise;
    } 
    // else- not in cache 
    $http.get('/someUrl', {id:id}).success(function(data){
        // Store your data or what ever.... 
        // Then resolve
        deferred.resolve(data);               
    }).error(function(data, status, headers, config) {
        deferred.reject("Error: request returned status " + status); 
    });
    return deferred.promise;

}

कंट्रोलर के अंदर…।

somethingService.getSomething(5).then(    
    function(thing) {     // On success
        alert(thing);
    },
    function(message) {   // On failure
        alert(message);
    }
);

मुझे उम्मीद है कि यह किसी की मदद करता है। मुझे अन्य उत्तर बहुत स्पष्ट नहीं मिले।


2
मैं शब्दों के साथ वर्णन नहीं कर सकता कि मैं कितना खुश हूं, आपने मुझे इतना समय बचा लिया!
रायलर

Http GET विफल होने की स्थिति में, लौटाया गया वादा इस तरह से अस्वीकार नहीं किया जाता है।
lex82

5
तो इस पद के लिए tl; dr है: हाँ, आप इसे वापस करने से पहले एक वादा हल कर सकते हैं, और यह शॉर्ट-सर्किट के रूप में करना होगा।
रे

1
यह उत्तर क्रिश कोवल के क्यू पर भी लागू होता है, जो कि कोणीय के वादे पर आधारित हैं।
कीथ

मैंने आपके उत्तर में एक त्रुटि-हैंडलिंग उदाहरण जोड़ा है, मुझे आशा है कि यह ठीक है।
साइमन ईस्ट

98

बस कोणीय 1.x में पूर्व-हल किए गए वादे को कैसे वापस करें

संकल्पित वचन:

return $q.when( someValue );    // angular 1.2+
return $q.resolve( someValue ); // angular 1.4+, alias to `when` to match ES6

अस्वीकृत वादा:

return $q.reject( someValue );

1
उस कारखाने के लिए कोई ज़रूरत नहीं है, उन सहायक कार्यों पहले से ही उपलब्ध हैं:{resolved: $q.when, rejected: $q.reject}
बर्गी

हे बर्गी, आपके बहुमूल्य योगदान के लिए धन्यवाद। मैंने उसी के अनुसार अपना उत्तर संपादित किया है।
एंड्री मिखायलोव - lolmaus

2
मुझे लगता है कि इस जवाब को चुना जाना चाहिए।
मोर्टेजा टूरानी

@mortezaT यदि इसे चुना गया था, तो यह मुझे एक गोल्डन बैज नहीं देगा। ;)
एंड्री मिखायलोव - lolmaus

6

यहां बताया गया है कि मैं आमतौर पर ऐसा कैसे करता हूं अगर मैं वास्तव में सरणी या ऑब्जेक्ट में डेटा कैश करना चाहता हूं

app.factory('DataService', function($q, $http) {
  var cache = {};
  var service= {       
    getData: function(id, callback) {
      var deffered = $q.defer();
      if (cache[id]) {         
        deffered.resolve(cache[id])
      } else {            
        $http.get('data.json').then(function(res) {
          cache[id] = res.data;              
          deffered.resolve(cache[id])
        })
      }
      return deffered.promise.then(callback)
    }
  }

  return service

})

DEMO


0

आप कैश तत्व को इनिशियलाइज़ करना भूल गए

function getSomething(id) {
    if (Cache[id]) {
        var deferred = $q.defer();
        deferred.resolve(Cache[id]); // <-- Can I do this?
        return deferred.promise;
    } else {
        Cache[id] = $http.get('/someUrl', {id:id});
        return Cache[id];
    }
}

माफ़ करना। यह सच है। मैं प्रश्न में स्पष्टता के लिए कोड को सरल बनाने की कोशिश कर रहा था। फिर भी, यदि यह पूर्व-हल किए गए वादे में जाता है, तो यह कॉलबैक नहीं लगता है।
क्रेग सेलेस्टे

2
मुझे नहीं लगता कि यदि आप किसी वादे के साथ एक वादे को हल करते हैं, तो आंतरिक वादा चपटा है। यह Cacheइच्छित ऑब्जेक्ट्स के बजाय वादों के साथ पॉप्युलेट करेगा और उन मामलों के लिए रिटर्न टाइप करेगा जब कोई ऑब्जेक्ट Cache में है और जब यह समान नहीं होगा। यह अधिक सही है, मुझे लगता है:$http.get('/someUrl', {id: id}).then(function (response) { Cache[id] = response.data; return Cache[id]; });
musically_ut

0

मुझे अपने संसाधन से डेटा प्राप्त करने के लिए किसी कारखाने का उपयोग करना पसंद है।

.factory("SweetFactory", [ "$http", "$q", "$resource", function( $http, $q, $resource ) {
    return $resource("/sweet/app", {}, {
        "put": {
            method: "PUT",
            isArray: false
        },"get": {
            method: "GET",
            isArray: false
        }
    });
}]);

फिर इस तरह से सेवा में मेरे मॉडल को उजागर करें

 .service("SweetService",  [ "$q", "$filter",  "$log", "SweetFactory",
    function ($q, $filter, $log, SweetFactory) {

        var service = this;

        //Object that may be exposed by a controller if desired update using get and put methods provided
        service.stuff={
            //all kinds of stuff
        };

        service.listOfStuff = [
            {value:"", text:"Please Select"},
            {value:"stuff", text:"stuff"}];

        service.getStuff = function () {

            var deferred = $q.defer();

          var promise = SweetFactory.get().$promise.then(
                function (response) {
                    if (response.response.result.code !== "COOL_BABY") {
                        deferred.reject(response);
                    } else {
                        deferred.resolve(response);
                        console.log("stuff is got", service.alerts);
                        return deferred.promise;
                    }

                }
            ).catch(
                function (error) {
                    deferred.reject(error);
                    console.log("failed to get stuff");
                }
            );

            promise.then(function(response){
                //...do some stuff to sett your stuff maybe fancy it up
                service.stuff.formattedStuff = $filter('stuffFormatter')(service.stuff);

            });


            return service.stuff;
        };


        service.putStuff = function () {
            console.log("putting stuff eh", service.stuff);

            //maybe do stuff to your stuff

            AlertsFactory.put(service.stuff).$promise.then(function (response) {
                console.log("yep yep", response.response.code);
                service.getStuff();
            }).catch(function (errorData) {
                alert("Failed to update stuff" + errorData.response.code);
            });

        };

    }]);

फिर मेरे नियंत्रक इसे शामिल कर सकते हैं और इसे उजागर कर सकते हैं या जो गिर गया है, वह उसके संदर्भ में सही है केवल इंजेक्शन सेवा का संदर्भ देकर।

ठीक काम करने लगता है। लेकिन मैं कोणीय के लिए नया हूँ। * त्रुटि हैंडलिंग ज्यादातर स्पष्टता के लिए छोड़ दिया है


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