Как $ http синхронный вызов с AngularJS
извините за мой вопрос новичка, но документация AngularJS не очень ясна или обширна для выяснения некоторых основных вещей.
есть ли способ сделать синхронный вызов с 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;
}
7 ответов:
в настоящее время нет. Если вы посмотрите на исходный код (с этого момента в октябре 2012 года), вы увидите, что вызов XHR open на самом деле жестко закодирован, чтобы быть асинхронным (третий параметр истинен):
xhr.open(method, url, true);вам нужно будет написать свой собственный сервис, который выполнял синхронные вызовы. Как правило, это не то, что вы обычно хотите сделать из-за характера выполнения JavaScript, вы в конечном итоге блокируете все остальное.
... но.. если блокировка все остальное на самом деле желательно, может быть, вам стоит заглянуть в обещания и $q service. Это позволяет вам ждать, пока не будет выполнен набор асинхронных действий, а затем выполнить что-то после их завершения. Я не знаю, каков ваш прецедент, но это может быть стоит посмотреть.
кроме того, если вы собираетесь свернуть свой собственный, больше информации о том, как сделать синхронные и асинхронные вызовы ajax можно посмотреть здесь.
I надеюсь, что это полезно.
я работал с фабрикой интегрированной с google maps автозаполнения и обещаний, я надеюсь, что вы служите.
http://jsfiddle.net/the_pianist2/vL9nkfe3/1/
вам нужно только заменить autocompleteService этим запросом с $ 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;
недавно я столкнулся с ситуацией, когда я хотел сделать вызовы $http, вызванные перезагрузкой страницы. Решение я пошел с:
- инкапсулировать два вызова в функции
- передайте второй вызов $http в качестве обратного вызова во вторую функцию
- вызов второй функции в apon .успех
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; };
вот как вы можете сделать это асинхронно и управлять вещи, как обычно. Все по-прежнему разделяют. Вы получаете ссылку на объект, который вы хотите обновить. Всякий раз, когда вы обновляете это в своем сервисе, он обновляется глобально без необходимости смотреть или возвращать обещание. Это очень приятно, потому что вы можете изменить базовый объект из службы без необходимости повторной привязки. Используя угловой способ, которым он должен использоваться. Я думаю, что это, вероятно, плохая идея сделайте $http.получить / опубликовать синхронно. Вы получите заметную задержку в сценарии.
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>
С синхронизация XHR является устаревшим, лучше не полагаться на это. Если вам нужно выполнить запрос на синхронизацию записей, вы можете использовать следующие помощники внутри службы для имитации записи формы.
он работает путем создания формы со скрытыми входами, которая отправляется по указанному 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(); }изменить в соответствии с вашими потребностями.
Как насчет упаковки вашего вызова в
Promise.all()метод, т. е.
Promise.all([$http.get(url).then(function(result){....}, function(error){....}])по данным MDN
обещание.все ждет всех свершений (или первого отказа)
Comments