I'm trying to make a single $http
request to get one of my JSON files and use the data across all my controllers.
I saw on egghead.io how to share data across multiple controllers, and I've also read this StackOverflow question: "Sharing a variable between controllers in angular.js".
However, the answers there don't use the $http
module. When using $http
, the controllers don't have the data to work on, and by the time the response is received it's already too late.
I then found the method $q.defer
and this question on StackOverflow: "AngularJS share asynchronous service data between controllers"
The solution posted there works fine, BUT it has two issues:
$http
request to obtain the same data already used in another controller; and,then
function.Below you can see my code:
controllers.js
'use strict';
/* Controllers */
function appInstallerListCtrl($scope, Data) {
$scope.apps = Data;
}
function appInstallerDetailCtrl($scope, $routeParams, Data) {
$scope.appId = $routeParams.appId;
$scope.apps = Data;
console.log($scope.apps); // <-- then function
console.log(Data); // <-- then function with $vv data returned but I can't access it
for (var i in $scope.apps) // <--- no way, baby!
console.log(i);
}
app.js
var app = angular.module('appInstaller', []);
app.factory('Data', function($http, $q) {
var defer = $q.defer();
$http.get('apps.json').then(function(result) {
defer.resolve(result.data.versions.version);
});
return defer.promise;
});
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/app', {templateUrl: 'partials/app-list.html', controller: appInstallerListCtrl}).
when('/app/:appId', {templateUrl: 'partials/app-detail.html', controller: appInstallerDetailCtrl}).
otherwise({redirectTo: '/app'});
}]);
What I'd like to have is that when launching the app, the $http
request will be performed and the response will be used throughout the app across all controllers.
Thanks
I like to store my data in the service, and return a promise to the controllers, because usually you need to deal with any errors there.
app.factory('Data', function($http, $q) {
var data = [],
lastRequestFailed = true,
promise;
return {
getApps: function() {
if(!promise || lastRequestFailed) {
// $http returns a promise, so we don't need to create one with $q
promise = $http.get('apps.json')
.then(function(res) {
lastRequestFailed = false;
data = res.data;
return data;
}, function(res) {
return $q.reject(res);
});
}
return promise;
}
}
});
.controller('appInstallerListCtrl', ['$scope','Data',
function($scope, Data) {
Data.getApps()
.then(function(data) {
$scope.data = data;
}, function(res) {
if(res.status === 500) {
// server error, alert user somehow
} else {
// probably deal with these errors differently
}
});
}]);
Any callbacks that are registered after a promise has been resolved/rejected will be resolved/rejected immediately with the same result/failure_reason. Once resolved/rejected, a promise can't change (its state). So the first controller to call getApps()
will create the promise. Any other controllers that call getApps()
will immediately get the promise returned instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With