我有一个问题,寻求建议,关于如何将存储在服务数组中的数据提供给控制器,因为在1.2中删除了解包承诺。
示例:
当路由一个最初加载时,服务将向服务器请求项目,将项目存储在服务中的数组中,因此每次请求路由一后只返回一个数组。保存项目时,该项目已被推送到服务中的数组。
如果我在初始加载时等待路由器1的控制器中的承诺,没有问题,因为响应被发回,但是在此之后路由一个的每个请求都会返回错误,因为我返回了一个数组。
关于如何在1.2中完成这样的事情的任何想法?
app.factory('Items',function($http) {
var items = [];
return {
list: function() {
if (items.length == 0) { // items array is empty so populate it and return list from server to controller
return $http.get('/?items').then(function(response) {
items = response.data.items;
return response.data.items;
});
}
return items; // items exist already so just return the array
},
save: function(item) {
return $http.post('/',{item:item}).then(function(response) {
items.push(item);
return response;
});
}
}
});
app.controller('RouteOne',function($scope,Items) {
Items.list().then(function(response) {
$scope.items = response;
});
/* used to be this before unwrapped promises were removed
$scope.items = Items.list();
*/
});
app.controller('RouteTwo',function($scope,Items) {
$scope.new_item = {};
$scope.addItem = function() {
Items.save($scope.new_item).then(function(response) {
$location.path('/'); // back to route one
});
};
});
答案 0 :(得分:5)
您可以让服务返回自己的承诺,可以使用缓存值或$ http承诺的结果来解析。我没有对此进行过全面测试,但它可能看起来像这样:
app.factory('Items', function($q, $http) {
var items = [];
return {
list: function() {
var deferred = $q.defer();
if (items.length == 0) { // items array is empty so populate it and return list from server to controller
$http.get('/?items').then(function(response) {
items = response.data.items;
deferred.resolve(response.data.items);
});
} else {
deferred.resolve(items); // items exist already so just return the array
}
return deferred.promise;
},
save: function(item) {
return $http.post('/',{item:item}).then(function(response) {
items.push(item);
return response;
});
}
}
});
app.controller('RouteOne',function($scope,Items) {
Items.list().then(function(response) {
$scope.items = response;
});
});
此外,根据您的特定用例,您可以将延迟移动到服务级别而不是功能级别,因为您只需要调用一次,但是我编写它的方式稍微灵活一点想要清除项目数组。
答案 1 :(得分:2)
此示例的主要思想是使用简单的js绑定对模型的引用。
Items.save
必须始终返回对其本地范围数组items
var app = angular.module('app', ['ui.router']);
app.config(function ($stateProvider) {
$stateProvider
.state('one', {
url: '/',
template: '<ul><li data-ng-repeat="item in items">{{item.value}}</li></ul><a href=#/two>Route two</a>',
controller: 'RouteOne'
})
.state('two', {
url: '/two',
template: '<input data-ng-model="new_item.value"></input><button data-ng-click="addItem()">Add item</button>',
controller: 'RouteTwo'
});
});
app.run(function ($state) {
$state.go('one');
});
app.factory('Items',function($http) {
var items = [];
return {
list: function() {
if (items.length === 0) { // items array is empty so populate it and return list from server to controller
// i just modified a little the request for jsfiddle
$http.get('/echo/jsonp/?items=[{"value": 1},{"value": 2},{"value": 3},{"value": 4},{"value": 5}]').then(function(response) {
// you won't need next line with a real server
response.data = JSON.parse(response.data.items);
Array.prototype.push.apply(items, response.data);
});
// simply always return the reference to items
// as it will be populated later
return items;
}
return items; // items exist already so just return the array
},
save: function(item) {
return $http.post('/echo/jsonp/',{item:item}).then(function(response) {
items.push(item);
return response;
});
}
}
});
app.controller('RouteOne',function($scope,Items) {
// don't do anything as you the binding does the work for you
$scope.items = Items.list();
});
app.controller('RouteTwo',function($scope,Items, $location) {
$scope.new_item = {};
$scope.addItem = function() {
Items.save($scope.new_item).then(function(response) {
$location.path('/'); // back to route one
});
};
});