[英]Angularjs: load data in service then load it to controllers
我在網上查了幾個解決方案,但我不太明白如何阻止控制器加載。 所以,我已經創建了一個plunkr來突出我想要做的事情。
基本上:我想加載服務中的所有數據,然后將該數據從該服務傳遞到每個控制器。 當應用程序首次加載時,因為它是Async,所以首先加載控制器。
我本可以在每個控制器中使用工廠,但我希望將該數據保存在服務的“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;
}
]);
plunkr: http ://plnkr.co/edit/ZvtYwXHSasC3fCAZKkDF?p = preview
我實際上沒有測試它,但看起來你需要創建並返回一個promise,以便在可用時返回數據。
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
因此您可以在所有控制器中使用該數據,而無需反復注入服務。
最后!!! 我管理做我想要的。
請注意,這不一定是最佳做法,但這是一個困擾我的問題,並想知道它是如何完成的。
我這樣做的方法是創建一個全局變量,我使用main resolve函數等待工廠執行http get,然后將其傳遞給服務。 然后,我在需要該數據的每個狀態上使用resolve並引用該函數。
更新:實現每次狀態變化時我都調用相同的工廠函數,所以我決定使用變量 - 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
同樣,工廠可以進行更多重構,並消除一些代碼,如緩存數據。 這樣,我們只去了一次工廠功能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.