Angularjs में $ http अनुरोध से प्रतिक्रिया आने तक इंतजार कैसे करें?


93

मैं कुछ डेटा का उपयोग कर रहा हूं जो कई पृष्ठों में एक RESTful सेवा से है। इसलिए मैं इसके लिए कोणीय कारखानों का उपयोग कर रहा हूं। इसलिए, मुझे सर्वर से एक बार डेटा प्राप्त करना आवश्यक है, और हर बार मुझे उस परिभाषित सेवा के साथ डेटा मिल रहा है। एक वैश्विक चर की तरह। यहाँ नमूना है:

var myApp =  angular.module('myservices', []);

myApp.factory('myService', function($http) {
    $http({method:"GET", url:"/my/url"}).success(function(result){
        return result;
    });
});

अपने नियंत्रक में मैं इस सेवा का उपयोग कर रहा हूं:

function myFunction($scope, myService) {
    $scope.data = myService;
    console.log("data.name"+$scope.data.name);
}

मेरी आवश्यकताओं के अनुसार इसका काम करना मेरे लिए ठीक है। लेकिन यहाँ समस्या यह है, जब मैंने अपने वेबपेज में पुनः लोड किया तो सेवा फिर से मिलेगी और सर्वर के लिए अनुरोध किया जाएगा। यदि कुछ अन्य फ़ंक्शन के बीच में जो "परिभाषित सेवा" पर निर्भर है, तो यह "कुछ" जैसी त्रुटि को अपरिभाषित है। इसलिए मैं अपनी स्क्रिप्ट में सेवा लोड होने तक इंतजार करना चाहता हूं। मैं उसे कैसे कर सकता हूँ? वहाँ वैसे भी angularjs में है?

जवाबों:


150

आपको Async ऑपरेशंस के लिए वादों का उपयोग करना चाहिए जहां आपको पता नहीं है कि यह कब पूरा होगा। एक वादा "एक ऑपरेशन का प्रतिनिधित्व करता है जो अभी तक पूरा नहीं हुआ है, लेकिन भविष्य में अपेक्षित है।" ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise )

एक उदाहरण कार्यान्वयन इस तरह होगा:

myApp.factory('myService', function($http) {

    var getData = function() {

        // Angular $http() and then() both return promises themselves 
        return $http({method:"GET", url:"/my/url"}).then(function(result){

            // What we return here is the data that will be accessible 
            // to us after the promise resolves
            return result.data;
        });
    };


    return { getData: getData };
});


function myFunction($scope, myService) {
    var myDataPromise = myService.getData();
    myDataPromise.then(function(result) {  

       // this is only run after getData() resolves
       $scope.data = result;
       console.log("data.name"+$scope.data.name);
    });
}

संपादित करें: सुजॉय के बारे में टिप्पणी करते हैं कि मुझे ऐसा करने की क्या आवश्यकता है ताकि myFuction () कॉल तब तक वापस नहीं आएगा। तब तक () फ़ंक्शन निष्पादन को पूरा नहीं करता है।

function myFunction($scope, myService) { 
    var myDataPromise = myService.getData(); 
    myDataPromise.then(function(result) { 
         $scope.data = result; 
         console.log("data.name"+$scope.data.name); 
    }); 
    console.log("This will get printed before data.name inside then. And I don't want that."); 
 }

अच्छा, चलो मान लेते हैं कि getData () को पूरा होने में 10 सेकंड लगे। यदि फ़ंक्शन उस समय में कुछ भी नहीं लौटाता है, तो यह प्रभावी रूप से सामान्य तुल्यकालिक कोड बन जाएगा और इसे पूरा होने तक ब्राउज़र को लटका देगा।

हालांकि वादे के साथ तुरंत लौटते हुए, ब्राउज़र इस बीच अन्य कोड के साथ जारी रखने के लिए स्वतंत्र है। एक बार वादा हल / विफल हो जाता है, तब () कॉल चालू हो जाता है। तो यह इस तरह से बहुत अधिक समझ में आता है, भले ही यह आपके कोड के प्रवाह को थोड़ा अधिक जटिल बना सकता है (जटिलता सामान्य रूप से async / समानांतर प्रोग्रामिंग की एक आम समस्या है!)


2
इससे मेरी समस्या हल हो गई !!! किसी और के लिए, मेरे पास एक ड्रॉपडाउन था जिसे अजाक्स कॉल से डेटा की आवश्यकता थी, इसलिए जब स्कोप बनाया गया था, तो डेटा उपलब्ध नहीं था। इस डिफरल के साथ, स्कोप को अजाक्स कॉल से आने वाले डेटा को सौंपा जा सकता है।
कैट लिम रुइज

8
@ मिकेल: मेरे यहाँ एक और सवाल है। आपका myFuction () कॉल तुरंत वापस आ जाएगा लेकिन वह वादा .then () बाद में कॉल करेगा। मुझे ऐसा करने की क्या आवश्यकता है ताकि myFuction () कॉल तब तक वापस नहीं आएगी। तब () फ़ंक्शन निष्पादन को पूरा करता है। function myFunction($scope, myService) { var myDataPromise = myService.getData(); myDataPromise.then(function(result) { $scope.data = result; console.log("data.name"+$scope.data.name); }); console.log("This will get printed before data.name inside then. And I don't want that."); }
सुजॉय

13

नए लोगों के लिए आप उदाहरण के लिए कॉलबैक का उपयोग कर सकते हैं:

आपकी सेवा में:

.factory('DataHandler',function ($http){

   var GetRandomArtists = function(data, callback){
     $http.post(URL, data).success(function (response) {
         callback(response);
      });
   } 
})

आपके नियंत्रक में:

    DataHandler.GetRandomArtists(3, function(response){
      $scope.data.random_artists = response;
   });

महान समाधान। उसी लाइन के साथ सोच रहा था जब मैं इसे देख रहा था। खुशी है कि किसी ने इसे बाहर रखा।
नैट

0

FYI करें, यह Angularfire का उपयोग कर रहा है इसलिए यह एक अलग सेवा या अन्य उपयोग के लिए थोड़ा भिन्न हो सकता है लेकिन उसी isse $ http का समाधान करना चाहिए। मेरे पास यही मुद्दा केवल समाधान था जो मेरे लिए सबसे अच्छा था, सभी सेवाओं / कारखानों को दायरे में एक ही वादे में संयोजित करना था। प्रत्येक मार्ग / दृश्य पर, जिसे इन सेवाओं / आदि को लोड करने की आवश्यकता होती है, मैं किसी भी कार्य को करता हूं जिसे नियंत्रक फ़ंक्शन के अंदर लोड किए गए डेटा की आवश्यकता होती है अर्थात myfunct () और मुख्य app.js रन के बाद ऑर्ट मैं डालते हैं

myservice.$loaded().then(function() {$rootScope.myservice = myservice;});

और देखने में मैंने सिर्फ किया

ng-if="myservice" ng-init="somevar=myfunct()"

पहले / मूल दृश्य तत्व / आवरण में, ताकि नियंत्रक सब कुछ अंदर चला सके

myfunct()

Async वादों / आदेश / कतार के मुद्दों के बारे में चिंता किए बिना। मुझे उम्मीद है कि मेरे पास उन्हीं मुद्दों के साथ कोई मदद करेगा।


0

मुझे भी यही समस्या हो रही थी और कोई नहीं अगर ये मेरे लिए काम करते। यहाँ क्या काम किया है, हालांकि ...

app.factory('myService', function($http) {
    var data = function (value) {
            return $http.get(value);
    }

    return { data: data }
});

और फिर इसका उपयोग करने वाला फ़ंक्शन है ...

vm.search = function(value) {

        var recieved_data = myService.data(value);

        recieved_data.then(
            function(fulfillment){
                vm.tags = fulfillment.data;
            }, function(){
                console.log("Server did not send tag data.");
        });
    };

यह सेवा आवश्यक नहीं है, लेकिन मुझे लगता है कि इसकी व्यापकता के लिए यह एक अच्छा अभ्यास है। ज्यादातर आपको किसी एक के लिए किसी अन्य की आवश्यकता होगी, खासकर एपीआई का उपयोग करते समय। वैसे भी मुझे उम्मीद है कि यह मददगार था।

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