AngularJS के साथ $ HTTP सिंक्रोनस कॉल कैसे करें


132

क्या एंगुलरजेएस के साथ एक तुल्यकालिक कॉल करने का कोई तरीका है?

कुछ मूल सामान का पता लगाने के लिए AngularJS प्रलेखन बहुत स्पष्ट या व्यापक नहीं है।

एक सेवा पर:

myService.getByID = function (id) {
    var retval = null;

    $http({
        url: "/CO/api/products/" + id,
        method: "GET"
    }).success(function (data, status, headers, config) {

        retval = data.Data;

    });

    return retval;
}

यह भी देखें groups.google.com/d/topic/angular/qagzXXhS_VI/discussion कैसे अतुल्यकालिक व्यवहार से निपटने के लिए के बारे में कुछ विचार के लिए: सर्वर साइड पर घटनाओं, $ घड़ी, प्रीलोड, वादा $ http से लौटे का उपयोग करें।
मार्क राजकॉक

1
अतुल्यकालिक हमेशा बेहतर होता है, खासकर जब आपके पास वादे होते हैं।
एंड्रयू जोसिन

कई बार, आप सिंक्रोनस कॉल से बच सकते हैं। देखें कि $ संसाधन कैसे कार्य करता है stackoverflow.com/questions/11966252/…
होनजजडे

3
@AndrewJoslin अतुल्यकालिक बदतर है जब आपको डिलीवरी का आदेश दिया जाता है।
स्टिजान वान एंटवर्पेन

जवाबों:


113

अभी नहीं। यदि आप स्रोत कोड (इस समय अक्टूबर 2012 से) को देखते हैं, तो आप देखेंगे कि XHR खुला कॉल वास्तव में हार्ड-कोडेड है अतुल्यकालिक (तीसरा पैरामीटर सच है):

 xhr.open(method, url, true);

आपको अपनी स्वयं की सेवा लिखने की आवश्यकता होगी जिसने सिंक्रोनस कॉल किया था। आम तौर पर ऐसा कुछ नहीं है जो आप आमतौर पर जावास्क्रिप्ट निष्पादन की प्रकृति के कारण करना चाहते हैं, आप अंत में बाकी सब कुछ अवरुद्ध कर देंगे।

... लेकिन .. अगर बाकी सब कुछ वास्तव में वांछित है, तो शायद आपको वादों और $ q सेवा पर ध्यान देना चाहिए । यह आपको तब तक इंतजार करने की अनुमति देता है जब तक कि अतुल्यकालिक कार्यों का एक सेट पूरा नहीं हो जाता है, और फिर सभी पूरा होने के बाद कुछ निष्पादित करें। मुझे नहीं पता कि आपका उपयोग मामला क्या है, लेकिन यह देखने लायक हो सकता है।

उसके बाहर, यदि आप अपना रोल करने जा रहे हैं, तो सिंक्रोनस और अतुल्यकालिक अजाक्स कॉल करने के बारे में अधिक जानकारी यहां पाई जा सकती है।

मुझे उम्मीद है कि सहायक है।


12
क्या आप $ q सेवा का उपयोग करने के लिए स्निपेट को कोड कर सकते हैं। मैंने कई विकल्पों की कोशिश की लेकिन यह एक अतुल्यकालिक तरीके से काम कर रहा है।
वेंकट

1
ऐसे स्थान हैं जहां यह समझ में आता है, उदाहरण के लिए, जब उपयोगकर्ता ब्राउज़र (ऑनबॉर्फ़नलोड) को बंद कर देता है, यदि आप सहेजना चाहते हैं तो आपको सिंक अनुरोध भेजना होगा, एक अन्य विकल्प एक डायलॉग रद्द करना है, और फिर विंडो को बंद करना है?
ब्रालियो

2
@ वेंकट: मुझे पता है कि यह एक देर से जवाब है, लेकिन जैसा कि मैंने जवाब में कहा है, कॉल हमेशा "अतुल्यकालिक" होगी, आपको बस $ q का उपयोग करना होगा ताकि प्रतिक्रिया के लिए प्रतीक्षा करें , फिर अपने तर्क को अंदर जारी रखें .then(callback)। की तरह कुछ: doSomething(); $http.get('/a/thing').then(doEverythingElse);
बेन लेश

3
निम्नलिखित वीडियो ने मुझे वादे का अध्ययन करने में मदद की, AngularJS वादा $ q के साथ
इल्या पालकिन

1
@BenLesh मैं आपके द्वारा डाले गए समय या किसी के द्वारा लगाए गए समय के बारे में अनभिज्ञ नहीं हूं। मैं आपके जवाब को डाउन-वोट करने के लिए स्वतंत्र हूं और कहता हूं कि अगर यह एक उदाहरण प्रदान किया गया होता तो यह मेरे लिए मददगार होता। मैंने आपका उत्तर देखा, इससे मुझे मदद नहीं मिली, इसलिए मैंने इसे वोट किया और टैब को बंद कर दिया, और उत्तर देने के लिए Google पर वापस गया जो मेरे लिए अधिक उपयोगी था। यह दुनिया का अंत नहीं है जब कोई आपके जवाब को डाउन-वोट करता है, और आपको बताता है कि इसे कैसे सुधार किया जा सकता है। क्या आपने टिप्पणी को छोड़ कर मुझे पसंद किया होगा कि क्यों? सिर्फ ईमानदार होने के नाते।
सर्किटरी

12

मैंने गूगल मैप्स के साथ एकीकृत फैक्ट्री के साथ काम किया है जो स्वत: पूर्ण और किए गए वादे हैं, मुझे उम्मीद है कि आप सेवा करेंगे।

http://jsfiddle.net/the_pianist2/vL9nkfe3/1/

आपको केवल कारखाने से पहले $ http incuida के साथ इस अनुरोध के द्वारा स्वतः पूर्ण सेवा को बदलने की आवश्यकता है।

app.factory('Autocomplete', function($q, $http) {

और $ http अनुरोध के साथ

 var deferred = $q.defer();
 $http.get('urlExample').
success(function(data, status, headers, config) {
     deferred.resolve(data);
}).
error(function(data, status, headers, config) {
     deferred.reject(status);
});
 return deferred.promise;

<div ng-app="myApp">
  <div ng-controller="myController">
  <input type="text" ng-model="search"></input>
  <div class="bs-example">
     <table class="table" >
        <thead>
           <tr>
              <th>#</th>
              <th>Description</th>
           </tr>
        </thead>
        <tbody>
           <tr ng-repeat="direction in directions">
              <td>{{$index}}</td>
              <td>{{direction.description}}</td>
           </tr>
        </tbody>
     </table>
  </div>

'use strict';
 var app = angular.module('myApp', []);

  app.factory('Autocomplete', function($q) {
    var get = function(search) {
    var deferred = $q.defer();
    var autocompleteService = new google.maps.places.AutocompleteService();
    autocompleteService.getPlacePredictions({
        input: search,
        types: ['geocode'],
        componentRestrictions: {
            country: 'ES'
        }
    }, function(predictions, status) {
        if (status == google.maps.places.PlacesServiceStatus.OK) {
            deferred.resolve(predictions);
        } else {
            deferred.reject(status);
        }
    });
    return deferred.promise;
};

return {
    get: get
};
});

app.controller('myController', function($scope, Autocomplete) {
$scope.$watch('search', function(newValue, oldValue) {
    var promesa = Autocomplete.get(newValue);
    promesa.then(function(value) {
        $scope.directions = value;
    }, function(reason) {
        $scope.error = reason;
    });
 });

});

सवाल खुद पर बनाया जाना है:

deferred.resolve(varResult); 

जब आपने अच्छा किया है और अनुरोध किया है:

deferred.reject(error); 

जब कोई त्रुटि होती है, और तब:

return deferred.promise;

5
var EmployeeController = ["$scope", "EmployeeService",
        function ($scope, EmployeeService) {
            $scope.Employee = {};
            $scope.Save = function (Employee) {                
                if ($scope.EmployeeForm.$valid) {
                    EmployeeService
                        .Save(Employee)
                        .then(function (response) {
                            if (response.HasError) {
                                $scope.HasError = response.HasError;
                                $scope.ErrorMessage = response.ResponseMessage;
                            } else {

                            }
                        })
                        .catch(function (response) {

                        });
                }
            }
        }]


var EmployeeService = ["$http", "$q",
            function ($http, $q) {
                var self = this;

                self.Save = function (employee) {
                    var deferred = $q.defer();                
                    $http
                        .post("/api/EmployeeApi/Create", angular.toJson(employee))
                        .success(function (response, status, headers, config) {
                            deferred.resolve(response, status, headers, config);
                        })
                        .error(function (response, status, headers, config) {
                            deferred.reject(response, status, headers, config);
                        });

                    return deferred.promise;
                };

4

मैं हाल ही में एक स्थिति में भाग गया, जहाँ मैं एक पृष्ठ पुनः लोड करके ट्रिगर की जाने वाली $ http कॉल करना चाहता था। समाधान मैं साथ चला गया:

  1. फ़ंक्शन में दो कॉल को एन्क्रिप्ट करें
  2. दूसरे फ़ंक्शन में कॉलबैक के रूप में दूसरा $ http कॉल पास करें
  3. एपन में दूसरा फ़ंक्शन कॉल करें। असफल

क्या होगा अगर इसके लूप के लिए, n बार कॉलिंग सर्वर के साथ।
मिथुन

2

यहाँ एक तरीका है कि आप इसे एसिंक्रोनस रूप से कर सकते हैं और सामान्य रूप से आपके जैसी चीजों का प्रबंधन कर सकते हैं। सब कुछ अभी भी साझा है। आपको उस ऑब्जेक्ट का संदर्भ मिलता है जिसे आप अपडेट करना चाहते हैं। जब भी आप अपनी सेवा में अपडेट करते हैं, तो यह बिना किसी वादे को देखने या वापस करने के लिए विश्व स्तर पर अपडेट हो जाता है। यह वास्तव में अच्छा है क्योंकि आप इस सेवा के भीतर से अंतर्निहित वस्तु को कभी भी बगावत किए बिना अपडेट कर सकते हैं। कोणीय का उपयोग करना जिस तरह से इसका उपयोग किया जाना है। मुझे लगता है कि $ http.get / पोस्ट सिंक्रोनस बनाने के लिए शायद यह एक बुरा विचार है। आपको स्क्रिप्ट में ध्यान देने योग्य देरी मिलेगी।

app.factory('AssessmentSettingsService', ['$http', function($http) {
    //assessment is what I want to keep updating
    var settings = { assessment: null };

    return {
        getSettings: function () {
             //return settings so I can keep updating assessment and the
             //reference to settings will stay in tact
             return settings;
        },
        updateAssessment: function () {
            $http.get('/assessment/api/get/' + scan.assessmentId).success(function(response) {
                //I don't have to return a thing.  I just set the object.
                settings.assessment = response;
            });
        }
    };
}]);

    ...
        controller: ['$scope', '$http', 'AssessmentSettingsService', function ($scope, as) {
            $scope.settings = as.getSettings();
            //Look.  I can even update after I've already grabbed the object
            as.updateAssessment();

और कहीं एक दृश्य में:

<h1>{{settings.assessment.title}}</h1>

0

चूंकि सिंक XHR है को जा रहा है, इसलिए उस पर भरोसा नहीं करना सबसे अच्छा है। यदि आपको किसी POST सिंक को करने की आवश्यकता है, तो आप एक फॉर्म पोस्ट का अनुकरण करने के लिए एक सेवा के अंदर निम्नलिखित सहायकों का उपयोग कर सकते हैं।

यह छिपे हुए इनपुट के साथ एक फॉर्म बनाकर काम करता है जो निर्दिष्ट URL पर पोस्ट किया जाता है।

//Helper to create a hidden input
function createInput(name, value) {
  return angular
    .element('<input/>')
    .attr('type', 'hidden')
    .attr('name', name)
    .val(value);
}

//Post data
function post(url, data, params) {

    //Ensure data and params are an object
    data = data || {};
    params = params || {};

    //Serialize params
    const serialized = $httpParamSerializer(params);
    const query = serialized ? `?${serialized}` : '';

    //Create form
    const $form = angular
        .element('<form/>')
        .attr('action', `${url}${query}`)
        .attr('enctype', 'application/x-www-form-urlencoded')
        .attr('method', 'post');

    //Create hidden input data
    for (const key in data) {
        if (data.hasOwnProperty(key)) {
            const value = data[key];
            if (Array.isArray(value)) {
                for (const val of value) {
                    const $input = createInput(`${key}[]`, val);
                    $form.append($input);
                }
            }
            else {
                const $input = createInput(key, value);
                $form.append($input);
            }
        }
    }

    //Append form to body and submit
    angular.element(document).find('body').append($form);
    $form[0].submit();
    $form.remove();
}

अपनी आवश्यकताओं के लिए आवश्यकतानुसार संशोधित करें।


-4

क्या एक Promise.all()विधि में अपनी कॉल लपेटने के बारे में यानी

Promise.all([$http.get(url).then(function(result){....}, function(error){....}])

एमडीएन के अनुसार

Promise.all सभी पूर्ति के लिए प्रतीक्षा करता है (या पहली अस्वीकृति)


तुम किस बारे में बात कर रहे हो? प्रश्न का कई वादों से कोई लेना-देना नहीं है ...
ओविदियु डोल्हा

यह एक या एक से अधिक वादा पूरा होने का इंतजार करेगा!
मंजीत दोसांझ

क्या आपने यह देखने के लिए इसका उपयोग किया है कि यह कैसे काम करता है? Promise.all एक और वादा वापस करेगा, यह सिंक को सिंक कॉल में परिवर्तित नहीं करता है
ओविदियु डोल्हा

हम्म ... ऐसा लगता है कि MDN प्रलेखन अस्पष्ट हो सकता है ... यह वास्तव में WAIT नहीं है जैसा कि उनके प्रलेखन में कहा गया है।
मंजीत दोसांझ

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