Angularjs:在服务中加载数据,然后将其加载到控制器
Angularjs: load data in service then load it to controllers
我已经在网上检查了几个解决方案,但我不太明白如何阻止控制器加载。所以,我创建了一个 plunkr 来突出我想做的事情。
基本上:我想加载服务中的所有数据,然后将该数据从该服务传递到每个控制器。首次加载应用时,由于它是异步的,因此首先加载控制器。
我本可以在每个控制器中使用工厂,但我想将数据保存在服务的"allProducts"属性中。我认为不需要在每次加载视图时调用工厂函数。
在示例中,我也尝试了 $q 服务,但在我看来,它具有与工厂中的 http 相同的行为,并且仍然需要在每次视图加载时调用 http 请求......
那么,有人可以帮助我完成此示例并实现一个优雅的解决方案吗?
app.factory('productsFactory', ['$http', '$q',
function($http, $q) {
var cachedData; //here we hold the data after the first api call
function getData(callback) {
if (cachedData) {
callback(cachedData);
} else {
$http.get('http://api.bestbuy.com/v1/products(longDescription=iPhone*|sku=7619002)?show=sku,name&pageSize=15&page=5&apiKey=bqs7a4gwmnuj9tq6bmyysndv&format=json')
.success(function(data) {
cachedData = data; //caching the data in a local variable
callback(data);
});
}
}
return {
getProds: getData
}
}
])
app.service('appService', ['productsFactory', '$q',
function(productsFactory, $q) {
var _this = this;
productsFactory.getProds(function(data) {
_this.allProducts = data; //wait for data to load before loading the controllers
})
}
])
app.controller('productsCtrl', ['$scope', 'appService',
function($scope, appService) {
$scope.myProducts = appService.allProducts;
}
]);
在这里:http://plnkr.co/edit/ZvtYwXHSasC3fCAZKkDF?p=preview
我实际上并没有测试它,但看起来你需要创建并返回一个承诺,以便在数据可用时返回数据。
app.factory('productsFactory', ['$http', '$q',
function($http, $q) {
var cachedData; //here we hold the data after the first api call
function getData(callback) {
var d = $q.defer();
if (cachedData) {
d.resolve(callback(cachedData));
} else {
$http.get('http://api.bestbuy.com/v1/products(longDescription=iPhone*|sku=7619002)?show=sku,name&pageSize=15&page=5&apiKey=bqs7a4gwmnuj9tq6bmyysndv&format=json')
.success(function(data) {
cachedData = data; //caching the data in a local variable
d.resolve(callback(cachedData));
});
}
return d.promise;
}
return {
getProds: getData
}
}
])
app.service('appService', ['productsFactory', '$q',
function(productsFactory, $q) {
var _this = this;
productsFactory.getProds(function(data) {
_this.allProducts = data; //wait for data to load before loading the controllers
})
}
])
app.controller('productsCtrl', ['$scope', 'appService',
function($scope, appService) {
$scope.myProducts = appService.allProducts;
}
]);
检查这个: http://plnkr.co/edit/ey0na3l2lyT0tUdbDyrf?p=preview
变化:
- 一个主应用程序控制器,用于包装您的所有应用程序。
在此控制器中,如果启动尚未完成其所有作业,我们将防止路由更改。启动完成后,我们将位置更改为主/默认路由。
- 在我们的run
块中,我们将bootStatus
VaR 设置为 false
并等待产品获取。
此外,我已将服务的结果存储到$rootScope
以便您可以在所有控制器中使用该数据,而无需一遍又一遍地注入服务。
我设法做到了我想要的。
请注意,这不一定是最佳实践,但这是一个困扰我并想知道它是如何完成的问题。
我这样做的方法是创建一个全局变量,在其中我使用一个主要的解析函数来等待工厂执行 http get,然后将其传递给服务。然后,我在需要该数据的每个状态上使用 resolve 并引用该函数。
更新:意识到每次状态为changins时我都会调用相同的工厂函数,所以我决定使用一个变量 - appService中的一个属性,当http get被调用一次时,它变为true:appService.retrieved并稍微更改了主要的解析函数。
var mainResolve = ['$q', 'appService', 'productsFactory', function($q, appService, productsFactory) {
var defer = $q.defer();
if(appService.retrieved) {
defer.resolve();
} else {
productsFactory.getProds(function(data) {
appService.allProducts = data;
defer.resolve();
})
appService.retrieved = true;
}
return defer.promise;
}]
而在州
.state('home', {
url: "/home",
templateUrl: "home.html",
controller: 'homeCtrl',
resolve: {
waitingFor: mainResolve
}
})
您可以在此处找到带有工作解决方案的 plnkr:http://plnkr.co/edit/ZvtYwXHSasC3fCAZKkDF?p=preview
同样,工厂可以再重构一些,并消除一些代码,如缓存数据。这样,我们只去一次工厂功能。
- AngularJS加载JSON数据,然后从中解析/加载HTML
- 先在Angular中加载配置文件,然后再加载其他文件
- 加载文件,然后调用回调函数
- 如何更改javascript的一个变量,然后运行;“加载”;而无需重新加载页面
- 下拉重新加载页面,然后检索值
- 先加载特定的图像,然后再加载页面的其余部分
- 加载页面,然后在页面加载时执行 javascript
- Angular js,在选择元素上,我想 POST 数据以将其保存在数据库中,然后我想使用 PUT 更新它而无需重新加载
- 使用 jQuery 加载 JSON,然后将其显示给查看器
- 淡出加载然后淡入不起作用
- 可以进行现场重新加载,然后触发点击功能
- 在RadWindow中加载新页面,然后从加载的窗体中关闭窗口
- 加载在JSBN中创建的RSA公钥,然后加密消息
- 加载时可以单击按钮#1,然后需要单击按钮#2两次.按钮#1也需要点击两次
- 地图,rails 4.2,javascript,鼠标悬停,只工作一次(或两次).然后在重新加载之后
- 如何在jQuery中进行页面加载,然后点击
- removeChild,然后再次添加以前删除的Child以重新加载并清理它
- jQuery UI#Accordion加载然后fadeIN..怎样
- 中间的页脚加载然后粘在底部
- 加载然后换行,但是换行在jQuery中不起作用