Вот Plunk, который делает то, что вы хотите: http://plnkr.co/edit/TTlbSv?p=preview
Идея состоит в том, что вы работаете с обещаниями напрямую и их «тогдашними» функциями для манипулирования и доступа к асинхронно возвращаемым ответам.
app.factory('myService', function($http) {
var myService = {
async: function() {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get('test.json').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
// Return the promise to the controller
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
// Call the async method and then do stuff with what is returned inside our own then function
myService.async().then(function(d) {
$scope.data = d;
});
});
Вот немного более сложная версия, которая кэширует запрос, поэтому вы делаете его только в первый раз ( http://plnkr.co/edit/2yH1F4IMZlMS8QsV9rHv?p=preview ):
app.factory('myService', function($http) {
var promise;
var myService = {
async: function() {
if ( !promise ) {
// $http returns a promise, which has a then function, which also returns a promise
promise = $http.get('test.json').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
}
// Return the promise to the controller
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
$scope.clearData = function() {
$scope.data = {};
};
$scope.getData = function() {
// Call the async method and then do stuff with what is returned inside our own then function
myService.async().then(function(d) {
$scope.data = d;
});
};
});
then
?myService.async()
несколько раз с разных контроллеров, как бы вы организовали сервис так, чтобы он выполнял только$http.get()
первый запрос, а все последующие запросы просто возвращают массив локальных объектов, который устанавливается при первом вызовеmyService.async()
. Другими словами, я хочу избежать множества ненужных запросов к сервису JSON, когда мне действительно нужно сделать только один.$scope.data = myService.async()
непосредственно в контроллере.Пусть это будет просто. Это так же просто, как
promise
в вашем сервисе (не нужно использоватьthen
в сервисе)then
в вашем контроллереDemo. http://plnkr.co/edit/cbdG5p?p=preview
источник
app.factory
, и в вашем коде этоapp.service
. Это предполагаетсяapp.factory
в этом случае.Поскольку он асинхронный,
$scope
он получает данные до завершения вызова ajax.Вы можете использовать
$q
в своем сервисе, чтобы создатьpromise
и вернуть его контроллеру, и контроллер получит результат в рамкахthen()
вызова противpromise
.К вашим услугам,
Затем в вашем контроллере:
источник
this.async = function() {
иthis.getData = function() {return data}
? Я надеюсь, вы понимаете, что я имею в видуdeffered = $q.defer()
в myService.async, если я хочу вызывать myService.async () два или более раз$q.defer
как$http
сервис уже возвращает обещание. Возвращенное обещание будет зависать, если$http
возвращается ошибка. В дополнение к этому.success
и.error
методы устарели и были удалены из AngularJS 1.6 .У tosh shimayama есть решение, но вы можете упростить многое, если используете тот факт, что $ http возвращает обещания, а обещания могут возвращать значение:
Небольшая демонстрация в coffeescript: http://plunker.no.de/edit/ksnErx?live=preview
Ваш плункер обновлен по моему методу: http://plnkr.co/edit/mwSZGK?p=preview
источник
Намного лучше, я думаю, что-то вроде этого:
Обслуживание:
А в контроллере вы можете просто использовать:
Angular автоматически поместит разрешенное
awesomeFruits
в$scope.fruits
.источник
У меня была такая же проблема, но когда я занимался серфингом в интернете, я понял, что $ http возвращает по умолчанию обещание, а затем я могу использовать его с «then» после возврата «data». посмотрите на код:
источник
При связывании пользовательского интерфейса с вашим массивом вам нужно будет убедиться, что вы обновляете тот же массив напрямую, устанавливая длину в 0 и помещая данные в массив.
Вместо этого (который устанавливает другую ссылку на массив, о
data
которой ваш пользовательский интерфейс не будет знать):попробуй это:
Вот скрипка, которая показывает разницу между установкой нового массива и его очисткой и добавлением к существующему. Я не мог заставить ваш plnkr работать, но, надеюсь, это работает для вас!
источник
angular.copy(d, data)
тоже будет работать. Когда в метод copy () передается адресат, он сначала удаляет элементы адресата, а затем копирует новые из источника.В связи с этим я столкнулся с подобной проблемой, но не с get или post, созданными Angular, а с расширением, сделанным сторонней организацией (в моем случае Chrome Extension).
Проблема, с которой я столкнулся, заключается в том, что расширение Chrome не вернется,
then()
поэтому я не смог сделать это так, как в приведенном выше решении, но результат все еще асинхронный.Поэтому я решил создать сервис и перейти к обратному вызову.
Тогда в моем контроллере
Надеюсь, что это может помочь другим получить ту же проблему.
источник
Я прочитал http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/ [AngularJS позволяет нам упростить логику нашего контроллера, поместив обещание непосредственно в область, а не вручную передавая разрешенную значение в обратном вызове успеха.]
так просто и удобно :)
Надеюсь это поможет
источник
defrred.promise
не является функцией.$scope.items = Data.getData();
устарела в AnglularМне действительно не нравится тот факт, что из-за «обещанного» способа работы потребитель службы, использующий $ http, должен «знать», как распаковать ответ.
Я просто хочу позвонить и вывести данные, как в старом
$scope.items = Data.getData();
стиле, который сейчас не рекомендуется .Я пытался некоторое время и не нашел идеального решения, но вот мой лучший шанс ( Плункер ). Это может быть полезно для кого-то.
Затем контроллер:
Я могу уже заметить недостатки
getData
может приниматьobj
параметр только в форме объекта (хотя он также может принимать массив), что не будет проблемой для многих приложений, но является серьезным ограничением$scope.data
с ,= {}
чтобы сделать его объектом ( по существу , что$scope.clearData()
делает выше), или= []
для массива, или он не будет работать (мы уже имея предположить , что - то о том , что грядет данные). Я пытался сделать этот шаг подготовки INgetData
, но не повезло.Тем не менее, он предоставляет шаблон, который удаляет шаблон контроллера "обещание разворачивания" и может быть полезен в тех случаях, когда вы хотите использовать определенные данные, полученные из $ http, в более чем одном месте, сохраняя их СУХОЙ.
источник
Что касается кэширования ответа в сервисе, вот еще одна версия, которая кажется более прямой, чем то, что я видел до сих пор:
эта услуга будет возвращать либо кэшированные данные или
$http.get
;источник
Пожалуйста, попробуйте следующий код
источник