Answers:
这是一个可以满足您需求的Plunk:http ://plnkr.co/edit/TTlbSv?p=preview
这个想法是您直接使用promise和它们的“ then”功能来操纵和访问异步返回的响应。
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;
});
};
});
myService.async()
从各个控制器多次调用,如何组织服务,以便仅对$http.get()
第一个请求执行,所有后续请求仅返回在第一次调用时设置的本地对象数组myService.async()
。换句话说,当我实际上只需要发出一个请求时,我想避免对JSON服务进行多个不必要的请求。
$scope.data = myService.async()
直接在控制器中使用。
简单一点。就这么简单
promise
您的服务(无需then
在服务中使用)then
在控制器中使用演示 http://plnkr.co/edit/cbdG5p?p=预览
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;
});
});
app.factory
在您的代码中为app.service
。app.factory
在这种情况下应该是这样。
因为它是异步的,$scope
所以Ajax调用完成之前正在获取数据。
您可以$q
在您的服务中使用来创建promise
并将其返回给控制器,然后控制器在then()
对的调用中获得结果promise
。
为您服务
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;
});
然后,在您的控制器中:
app.controller('MainCtrl', function( myService,$scope) {
myService.async().then(function() {
$scope.data = myService.data();
});
});
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返回promise并且promise可以返回值的事实,则可以简化很多工作:
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
}
});
});
coffeescript中的一些演示:http ://plunker.no.de/edit/ksnErx?live=preview
您的窃听器已通过我的方法进行了更新:http ://plnkr.co/edit/mwSZGK?p=preview
我认为更好的方法是这样的:
服务:
app.service('FruitsManager',function($q){
function getAllFruits(){
var deferred = $q.defer();
...
// somewhere here use: deferred.resolve(awesomeFruits);
...
return deferred.promise;
}
return{
getAllFruits:getAllFruits
}
});
在控制器中,您可以简单地使用:
$scope.fruits = FruitsManager.getAllFruits();
Angular会自动将已解析的内容awesomeFruits
放入$scope.fruits
。
我遇到了同样的问题,但是当我在互联网上冲浪时,我了解到$ http默认会返回一个承诺,那么我可以在返回“数据”之后将其与“ then”一起使用。看一下代码:
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;
});
});
将UI绑定到数组时,您需要通过将长度设置为0并将数据推入数组来确保直接更新同一数组。
而不是此设置(它设置了data
您的UI不会知道的其他数组引用):
myService.async = function() {
$http.get('test.json')
.success(function (d) {
data = d;
});
};
试试这个:
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]);
}
});
};
这是一个小提琴,显示了设置新数组与清空与添加到现有数组之间的区别。我无法让您的plnkr工作,但希望这对您有用!
angular.copy(d, data)
也可以。当将目标提供给copy()方法时,它将首先删除目标的元素,然后从源中复制新的元素。
与此相关的是,我遇到了类似的问题,但是不是通过Angular进行的get或post而是通过第三方进行的扩展(在我的情况下为Chrome扩展)。
我面临的问题是Chrome扩展程序不会返回,then()
因此我无法按照上述解决方案的方式进行操作,但结果仍然是异步的。
所以我的解决方案是创建服务并进行回调
app.service('cookieInfoService', function() {
this.getInfo = function(callback) {
var model = {};
chrome.cookies.get({url:serverUrl, name:'userId'}, function (response) {
model.response= response;
callback(model);
});
};
});
然后在我的控制器中
app.controller("MyCtrl", function ($scope, cookieInfoService) {
cookieInfoService.getInfo(function (info) {
console.log(info);
});
});
希望这可以帮助其他人解决同样的问题。
我已经阅读了http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/ [AngularJS允许我们通过将诺言直接放在范围上来简化控制器逻辑,而不是手动将已解决的问题成功回调中的值。]
很简单方便:)
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();
});
希望有帮助
defrred.promise
不是函数。
$scope.items = Data.getData();
被弃用Anglular
我真的不喜欢这样的事实,由于“承诺”的处理方式,使用$ http的服务的使用者必须“知道”如何解压缩响应。
我只想调用一些东西并取出数据,类似于现在不推荐使用的旧$scope.items = Data.getData();
方法。
我尝试了一段时间,但没有提出完美的解决方案,但这是我的最佳拍档(Plunker)。对某人可能有用。
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;
});
然后控制器:
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
};
});
我已经发现的缺陷是
getData
只能接受obj
对象形式的参数(尽管它也可以接受数组),这在许多应用程序中不会有问题,但这是一个严重的限制$scope.data
以= {}
使它的对象(基本上就是$scope.clearData()
上面的一样),或者= []
为一个数组,否则将无法工作(我们已经不得不承担一些关于什么样的数据来了)。我试图在IN进行此准备步骤getData
,但是没有运气。但是,它提供了一种删除控制器“承诺解开”样板的模式,在希望将从$ http获得的某些数据在多个位置使用而保持其DRY的情况下,该模式很有用。
就在服务中缓存响应而言,这是另一个版本,它比我到目前为止看到的更为直接:
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;
});
})();
});
该服务将返回缓存的数据或$http.get
;
dataStorage.then(function(data) {
$scope.data = data;
},function(e){
console.log('err: ' + e);
});
请尝试以下代码
您可以拆分控制器(PageCtrl)和服务(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;
});
}
}
}());
then
?