Przetwarzanie odpowiedzi $ http w serwisie
Ostatnio zamieściłem szczegółowy opis problemu, z którym się borykam tutaj W SO. Ponieważ nie mogłem wysłać rzeczywistego żądania $http
, użyłem timeoutu do symulacji asynchronicznego zachowania. Powiązanie danych z mojego modelu do widoku działa poprawnie, z pomocą @ Gloopy
Teraz, Kiedy używam $http
zamiast $timeout
(testowane lokalnie), widziałem, że żądanie asynchroniczne zakończyło się sukcesem i data
jest wypełnione odpowiedzią json w moim serwisie. Ale mój pogląd nie jest aktualizowany.
Zaktualizowano Plunkr tutaj
12 answers
Oto Plunk, który robi to, co chcesz: http://plnkr.co/edit/TTlbSv?p=preview
Chodzi o to, że pracujesz bezpośrednio z obietnicami i ich funkcjami "wtedy", aby manipulować i uzyskiwać dostęp do asynchronicznie zwracanych odpowiedzi.
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;
});
});
Tutaj jest nieco bardziej skomplikowana wersja, która buforuje żądanie, więc robisz to tylko za pierwszym razem ( 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;
});
};
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-06 21:21:59
Niech to będzie proste. To tak proste jak
- Return
promise
in your service (no need to usethen
in service) - Użyj
then
w kontrolerze
Demo. http://plnkr.co/edit/cbdG5p?p=preview
var app = angular.module('plunker', []);
app.factory('myService', function($http) {
return {
async: function() {
return $http.get('test.json'); //1. this returns promise
}
};
});
app.controller('MainCtrl', function( myService,$scope) {
myService.async().then(function(d) { //2. so you can use .then()
$scope.data = d;
});
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-04 19:09:58
Ponieważ jest asynchroniczny, $scope
pobiera dane przed zakończeniem wywołania ajax.
Możesz użyć $q
w swoim serwisie, aby utworzyć promise
i oddać go do
kontroler i kontroler uzyskują wynik w wywołaniu then()
przeciwko promise
.
W Twojej służbie,
app.factory('myService', function($http, $q) {
var deffered = $q.defer();
var data = [];
var myService = {};
myService.async = function() {
$http.get('test.json')
.success(function (d) {
data = d;
console.log(d);
deffered.resolve();
});
return deffered.promise;
};
myService.data = function() { return data; };
return myService;
});
Następnie w kontrolerze:
app.controller('MainCtrl', function( myService,$scope) {
myService.async().then(function() {
$scope.data = myService.data();
});
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-20 05:35:40
Tosh shimayama ma rozwiązanie, ale możesz znacznie uprościć, jeśli użyjesz faktu, że $http zwraca obietnice i że obietnice mogą zwrócić wartość:
app.factory('myService', function($http, $q) {
myService.async = function() {
return $http.get('test.json')
.then(function (response) {
var data = reponse.data;
console.log(data);
return data;
});
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
$scope.asyncData = myService.async();
$scope.$watch('asyncData', function(asyncData) {
if(angular.isDefined(asyncData)) {
// Do something with the returned data, angular handle promises fine, you don't have to reassign the value to the scope if you just want to use it with angular directives
}
});
});
Mała demonstracja w coffeescript: http://plunker.no.de/edit/ksnErx?live=preview
Your plunker updated with my method: http://plnkr.co/edit/mwSZGK?p=preview
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-20 12:02:10
O wiele lepszy sposób myślę, że byłoby coś takiego:
Usługa:
app.service('FruitsManager',function($q){
function getAllFruits(){
var deferred = $q.defer();
...
// somewhere here use: deferred.resolve(awesomeFruits);
...
return deferred.promise;
}
return{
getAllFruits:getAllFruits
}
});
A w kontrolerze można po prostu użyć:
$scope.fruits = FruitsManager.getAllFruits();
Angular automatycznie umieści awesomeFruits
w $scope.fruits
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-03 15:11:51
Miałem ten sam problem, ale gdy surfowałem po Internecie zrozumiałem, że $http zwraca domyślnie obietnicę, wtedy mogę użyć go z "then" po zwróceniu "danych". spójrz na kod:
app.service('myService', function($http) {
this.getData = function(){
var myResponseData = $http.get('test.json').then(function (response) {
console.log(response);.
return response.data;
});
return myResponseData;
}
});
app.controller('MainCtrl', function( myService, $scope) {
// Call the getData and set the response "data" in your scope.
myService.getData.then(function(myReponseData) {
$scope.data = myReponseData;
});
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-19 23:20:54
Podczas wiązania interfejsu użytkownika z tablicą będziesz chciał się upewnić, że zaktualizujesz tę samą tablicę bezpośrednio, ustawiając długość na 0 i wpychając dane do tablicy.
Zamiast tego (które ustawia inne odniesienie do tablicy na data
, o którym twój interfejs nie będzie wiedział):
myService.async = function() {
$http.get('test.json')
.success(function (d) {
data = d;
});
};
Spróbuj tego:
myService.async = function() {
$http.get('test.json')
.success(function (d) {
data.length = 0;
for(var i = 0; i < d.length; i++){
data.push(d[i]);
}
});
};
Oto fiddle , który pokazuje różnicę między ustawieniem nowej tablicy a opróżnieniem i dodaniem do istniejącej. Nie udało mi się uruchomić twojego plnkr, ale mam nadzieję, że to działa dla Ciebie!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-20 05:00:39
W związku z tym miałem podobny problem, ale nie z get lub post wykonane przez Angular, ale z rozszerzeniem wykonane przez 3rd party (w moim przypadku rozszerzenie Chrome).
Problem, z którym się spotkałem, polega na tym, że rozszerzenie Chrome nie zwróci then()
, więc nie byłem w stanie zrobić tego tak, jak w powyższym rozwiązaniu, ale wynik jest nadal asynchroniczny.
Więc moim rozwiązaniem jest stworzenie usługi i przejść do callback
app.service('cookieInfoService', function() {
this.getInfo = function(callback) {
var model = {};
chrome.cookies.get({url:serverUrl, name:'userId'}, function (response) {
model.response= response;
callback(model);
});
};
});
Potem w moim kontrolerze
app.controller("MyCtrl", function ($scope, cookieInfoService) {
cookieInfoService.getInfo(function (info) {
console.log(info);
});
});
Mam nadzieję, że to pomoże innym mam ten sam problem.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-23 11:52:46
Przeczytałem http://markdalgleish.com/2013/06/using-promises-in-angularjs-views / [AngularJS pozwala nam usprawnić naszą logikę kontrolera, umieszczając obietnicę bezpośrednio na zakresie, a nie ręcznie przekazując rozwiązaną wartość w odpowiedzi zwrotnej sukcesu.]
Takie proste i poręczne:)
var app = angular.module('myApp', []);
app.factory('Data', function($http,$q) {
return {
getData : function(){
var deferred = $q.defer();
var promise = $http.get('./largeLoad').success(function (response) {
deferred.resolve(response);
});
// Return the promise to the controller
return deferred.promise;
}
}
});
app.controller('FetchCtrl',function($scope,Data){
$scope.items = Data.getData();
});
Hope this help
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-13 16:22:20
Naprawdę nie podoba mi się to, że ze względu na "obiecujący" sposób robienia rzeczy, konsument usługi używającej $http musi "wiedzieć" jak rozpakować odpowiedź.
Chcę po prostu zadzwonić i wyciągnąć dane, podobne do starego $scope.items = Data.getData();
sposobu, który jest teraz przestarzały .
Próbowałem przez jakiś czas i nie wymyśliłem idealnego rozwiązania, ale oto mój najlepszy strzał (Plunker ). Może się komuś przydać.
app.factory('myService', function($http) {
var _data; // cache data rather than promise
var myService = {};
myService.getData = function(obj) {
if(!_data) {
$http.get('test.json').then(function(result){
_data = result.data;
console.log(_data); // prove that it executes once
angular.extend(obj, _data);
});
} else {
angular.extend(obj, _data);
}
};
return myService;
});
Then kontroler:
app.controller('MainCtrl', function( myService,$scope) {
$scope.clearData = function() {
$scope.data = Object.create(null);
};
$scope.getData = function() {
$scope.clearData(); // also important: need to prepare input to getData as an object
myService.getData($scope.data); // **important bit** pass in object you want to augment
};
});
Wady, które już dostrzegam to
- musisz przekazać obiekt, w którym chcesz dane dodane do, co nie jest intuicyjnym lub powszechnym wzorcem w Angular
-
getData
może akceptować tylko parametrobj
w postaci obiektu (chociaż może również akceptować tablicę), co nie będzie problemem dla wielu aplikacji, ale jest bolesnym ograniczeniem - musisz przygotować obiekt wejściowy
$scope.data
z= {}
aby uczynić go obiektem (zasadniczo to, co$scope.clearData()
robi powyżej), lub= []
dla tablicy, albo nie będzie działać(już musimy założyć coś o tym, jakie dane nadchodzą). Próbowałem zrobić ten etap przygotowaniagetData
, ale bez powodzenia.
Niemniej jednak dostarcza wzorzec, który usuwa płytkę kotła kontrolera "promise unwrap" i może być przydatny w przypadkach, gdy chcemy użyć pewnych danych uzyskanych z $http w więcej niż jednym miejscu, utrzymując je w stanie suchym.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-24 17:43:16
Jeśli chodzi o buforowanie odpowiedzi w serwisie, oto inna wersja, która wydaje się bardziej prosta niż to, co widziałem do tej pory:
App.factory('dataStorage', function($http) {
var dataStorage;//storage for cache
return (function() {
// if dataStorage exists returned cached version
return dataStorage = dataStorage || $http({
url: 'your.json',
method: 'GET',
cache: true
}).then(function (response) {
console.log('if storage don\'t exist : ' + response);
return response;
});
})();
});
Ta usługa zwróci dane z pamięci podręcznej lub $http.get
;
dataStorage.then(function(data) {
$scope.data = data;
},function(e){
console.log('err: ' + e);
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-14 09:53:42
Proszę wypróbować poniższy kod
Możesz podzielić kontroler (PageCtrl) i usługę (dataService)
'use strict';
(function () {
angular.module('myApp')
.controller('pageContl', ['$scope', 'dataService', PageContl])
.service('dataService', ['$q', '$http', DataService]);
function DataService($q, $http){
this.$q = $q;
this.$http = $http;
//... blob blob
}
DataService.prototype = {
getSearchData: function () {
var deferred = this.$q.defer(); //initiating promise
this.$http({
method: 'POST',//GET
url: 'test.json',
headers: { 'Content-Type': 'application/json' }
}).then(function(result) {
deferred.resolve(result.data);
},function (error) {
deferred.reject(error);
});
return deferred.promise;
},
getABCDATA: function () {
}
};
function PageContl($scope, dataService) {
this.$scope = $scope;
this.dataService = dataService; //injecting service Dependency in ctrl
this.pageData = {}; //or [];
}
PageContl.prototype = {
searchData: function () {
var self = this; //we can't access 'this' of parent fn from callback or inner function, that's why assigning in temp variable
this.dataService.getSearchData().then(function (data) {
self.searchData = data;
});
}
}
}());
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-23 01:37:41