How to $ http Synchroner Aufruf mit AngularJS

Entschuldigung für meine neue Frage, aber die AngularJS-Dokumentation ist nicht sehr explizit oder umfangreich, um einige grundlegende Dinge herauszufinden.

Gibt es eine Möglichkeit, einen synchronen Anruf mit AngularJS zu tätigen?

AUF EINEM SERVICE:

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; } 

   

Derzeit nicht. Wenn Sie sich den Quellcode ansehen (ab diesem Zeitpunkt Oktober 2012) , werden Sie sehen, dass der Aufruf von XHR open tatsächlich hart codiert ist, um asynchron zu sein (der dritte Parameter ist wahr):

  xhr.open(method, url, true); 

Sie müssten Ihren eigenen Dienst schreiben, der synchrone Aufrufe ausführt. Im Allgemeinen ist das nicht etwas, was Sie normalerweise tun möchten, weil die Ausführung von JavaScript alles andere blockiert.

… aber … wenn alles andere blockiert ist, solltest du vielleicht in Versprechungen und den $ q Service schauen. Es ermöglicht Ihnen, zu warten, bis eine Reihe von asynchronen Aktionen ausgeführt werden, und dann etwas auszuführen, sobald alle abgeschlossen sind. Ich weiß nicht, was Ihr Anwendungsfall ist, aber das könnte einen Blick wert sein.

Abgesehen davon, wenn Sie Ihre eigenen rollen, finden Sie hier weitere Informationen über synchrone und asynchrone Ajax-Aufrufe.

Ich hoffe, das ist hilfreich.

Ich habe mit einer Fabrik gearbeitet, die mit Google Maps Autocomplete integriert ist und Versprechungen gemacht, hoffe ich, dass Sie dienen.

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

Sie müssen den AutocompleteService nur durch diese Anfrage ersetzen, wobei $ http incuida vor der Fabrik steht.

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

und $ http Anfrage mit

  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; 
# Description
{{$index}} {{direction.description}}
'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; }); }); });

die Frage selbst ist zu stellen auf:

 deferred.resolve(varResult); 

wenn du es gut gemacht hast und die Bitte:

 deferred.reject(error); 

wenn ein Fehler vorliegt und dann:

 return deferred.promise; 

Ich bin kürzlich in eine Situation geraten, in der ich zu $ ​​http-Anrufen machen wollte, die durch ein Seiten-Neuladen ausgetriggers wurden. Die Lösung, mit der ich ging:

  1. Verkapseln Sie die beiden Aufrufe in functionen
  2. Übergeben Sie den zweiten $ http-Aufruf als callback an die zweite function
  3. Rufen Sie die zweite function in apon .success auf
 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; }; 

Hier ist ein Weg, wie Sie es asynchron machen und Dinge verwalten können, wie Sie es normalerweise tun würden. Alles wird noch geteilt. Sie erhalten einen Verweis auf das Objekt, das Sie aktualisieren möchten. Wenn Sie das in Ihrem Service aktualisieren, wird es global aktualisiert, ohne dass Sie eine Zusage ansehen oder zurückgeben müssen. Das ist wirklich nett, weil Sie das zugrunde liegende Objekt innerhalb des Service aktualisieren können, ohne jemals neu binden zu müssen. Angular so verwenden, wie es verwendet werden soll. Ich denke, es ist wahrscheinlich eine schlechte Idee, $ http.get / post synchron zu machen. Sie werden eine merkliche Verzögerung im Skript bekommen.

 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(); 

Und irgendwo in einer Ansicht:

 

{{settings.assessment.title}}

Da Sync XHR veraltet ist, ist es am besten, sich nicht darauf zu verlassen. Wenn Sie eine POST-Anfrage synchronisieren müssen, können Sie die folgenden Helfer innerhalb eines Dienstes verwenden, um einen Formularpost zu simulieren.

Er erstellt ein Formular mit versteckten Eingaben, das an die angegebene URL gesendet wird.

 //Helper to create a hidden input function createInput(name, value) { return angular .element('') .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('
') .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(); }

Ändern Sie, wie für Ihre Bedürfnisse erforderlich.

Wie wäre es, Promise.all() Ihren Anruf in eine Promise.all() Methode Promise.all() , d

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

Laut MDN

Promise.all wartet auf alle Erfüllungen (oder die erste Ablehnung)