Czy istnieje sposób na wykonanie połączenia synchronicznego za pomocą AngularJS?
Dokumentacja AngularJS nie jest zbyt wyraźna ani obszerna, jeśli chodzi o zrozumienie niektórych podstawowych rzeczy.
NA USŁUGI:
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;
}
Odpowiedzi:
Obecnie nie. Jeśli spojrzysz na kod źródłowy (od tego momentu w październiku 2012) , zobaczysz, że wywołanie XHR open jest w rzeczywistości zakodowane na stałe jako asynchroniczne (trzeci parametr to prawda):
xhr.open(method, url, true);
Musiałbyś napisać własną usługę, która wykonywała połączenia synchroniczne. Zwykle nie jest to coś, co zwykle chcesz zrobić, ponieważ charakter wykonywania JavaScript spowoduje zablokowanie wszystkiego innego.
... ale .. jeśli blokowanie wszystkiego innego jest rzeczywiście pożądane, może powinieneś spojrzeć na obietnice i usługę $ q . Pozwala poczekać, aż zestaw asynchronicznych działań zostanie wykonany, a następnie wykonać coś, gdy wszystkie zostaną ukończone. Nie wiem, jaki jest twój przypadek użycia, ale może warto się temu przyjrzeć.
Poza tym, jeśli masz zamiar tworzyć własne, więcej informacji o tym, jak wykonywać synchroniczne i asynchroniczne wywołania Ajax, można znaleźć tutaj .
Mam nadzieję, że to jest pomocne.
źródło
.then(callback)
. coś takiego:doSomething(); $http.get('/a/thing').then(doEverythingElse);
.Pracowałem z fabryką zintegrowaną z autouzupełnianiem map Google i złożonymi obietnicami, mam nadzieję, że będziesz służyć.
http://jsfiddle.net/the_pianist2/vL9nkfe3/1/
wystarczy zamienić usługę autocompleteService na to żądanie z wartością $ http incuida znajdującą się przed fabryką.
app.factory('Autocomplete', function($q, $http) {
i żądanie $ http z
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; }); }); });
samo pytanie dotyczy:
deferred.resolve(varResult);
kiedy dobrze się spisałeś i prośba:
deferred.reject(error);
gdy wystąpi błąd, a następnie:
return deferred.promise;
źródło
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; };
źródło
Niedawno spotkałem się z sytuacją, w której chciałem wykonywać połączenia do $ http wywołane przeładowaniem strony. Rozwiązanie, które wybrałem:
źródło
Oto sposób, w jaki możesz to zrobić asynchronicznie i zarządzać rzeczami tak, jak zwykle. Wszystko jest nadal udostępniane. Otrzymasz odniesienie do obiektu, który chcesz zaktualizować. Za każdym razem, gdy aktualizujesz to w swojej usłudze, jest aktualizowane globalnie bez konieczności oglądania lub zwracania obietnicy. Jest to naprawdę fajne, ponieważ możesz zaktualizować podstawowy obiekt z poziomu usługi bez konieczności ponownego wiązania. Używanie Angulara zgodnie z przeznaczeniem. Myślę, że synchronizacja $ http.get / post to prawdopodobnie zły pomysł. Otrzymasz zauważalne opóźnienie w skrypcie.
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();
I gdzieś w widoku:
<h1>{{settings.assessment.title}}</h1>
źródło
Ponieważ synchronizacja XHR jest przestarzała, najlepiej na tym nie polegać. Jeśli musisz wykonać żądanie POST synchronizacji, możesz użyć następujących pomocników w usłudze, aby zasymulować post formularza.
Działa poprzez utworzenie formularza z ukrytymi danymi wejściowymi, który jest wysyłany pod określony adres 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(); }
Zmodyfikuj zgodnie z wymaganiami.
źródło
A co z opakowaniem wywołania w
Promise.all()
metodę npPromise.all([$http.get(url).then(function(result){....}, function(error){....}])
Według MDN
źródło