I was just playing around with angular and its DI. I tried to use the promises paradigm as well, however I encountered a rather strange problem, using it in a Chrome Extension.
The following code works beautifully. The promise is resolved, when cb() in the object literal in the "chromeStorageService" is called.
But when I uncomment the return chrome.storage.local; the code stops working. I can't understand why, because the console.log('going to be resolved'); still gets fired, but the success alert does not. Thanks in advance for any tip :)
https://developer.chrome.com/extensions/storage.html
'use strict';
var app = {};
app = angular.module('options', ['options.controllers']);
app.services = angular.module('options.services', []);
app.services.factory('chromeStorageService', function () {
//return chrome.storage.local;
return {
get: function(id, cb) {
cb();
}
}
});
app.services.factory('storageService', ['chromeStorageService', '$q', function (chromeStorage, $q) {
return new function () {
this.get = function (identifier) {
var defered = $q.defer();
chromeStorage.get(identifier, function (items) {
var error = false//chrome.runtime.lastError;
if (error) {
return defered.reject(error);
}
console.log('going to be resolved');
console.log(defered);
defered.resolve();
});
return defered.promise;
}
}
}]);
app.services.factory('fooService', ['storageService', function (testService) {
return new function () {
this.getAll = function () {
var promise = testService.get('foo');
console.log(promise);
promise.then(
function () {
alert('success');
}, function () {
aler('err');
}
);
}
}
}]);
app.directive('foo', ['fooService', function (fooService) {
return {
restrict:'A',
link:function (scope, elm, attrs, ctrl) {
fooService.getAll();
}
};
}]);
app.controllers = angular.module('options.controllers', ['options.services']);
Angular has its own little event loop thing. When you .resolve a promise, that goes into Angular's queue. Stuff only happens when Angular clears its queue.
The usual thing is to do something like:
$scope.$apply(function() {
promise.resolve(thing);
});
And when control returns to $apply from the function you passed to it, it clears the queue and everything is beautiful. In this case you probably need to inject $rootScope into the service so you have something to apply, as per The view is not updated in AngularJS.
Your stub works because the stub never leaves angular-world, so you're already in a context that will look after the queue. When you use chrome.storage.local, your callback is not called from such a context.
I met the same problem today. I want to integrate chrome.storage.local.get with Angular promise pattern cause chrome.storage.local.get is asynchronous function. That's how i was doing:
// service
angular.module('app').factory('STORAGE', function($q) {
return {
get: function(key) {
var deferred = $q.defer();
chrome.storage.local.get(key, function(data) {
deferred.resolve(data[key]);
});
return deferred.promise;
},
set: function(key, value) {
var deferred = $q.defer();
var data = {};
data[key] = value;
chrome.storage.local.set(data, function() {
deferred.resolve({});
});
return deferred.promise;
},
del: function(key) {
var deferred = $q.defer();
chrome.storage.local.remove(key, function() {
deferred.resolve({});
});
return deferred.promise;
}
}
});
I define a Angular service call STORAGE that i can encapsulate chrome.storage.local. get, set and del method.
Then we can inject STORAGE to Angular route resolve part
// route resolve
...
resolve: {
hasToken: function(STORAGE) {
return (STORAGE.get('instagram_access_token')) ? true : false;
}
}
...
Inject route resolve parameter and STORAGE to controller
// controller
angular.module('app').controller('HomeController', ['$scope', 'hasToken', 'STORAGE',
function($scope, hasToken, STORAGE) {
$scope.hasToken = hasToken;
if ($scope.hasToken) {
STORAGE.get('profile').then(function(data) {
$scope.user = data;
});
}
}
]);
It does work well.
Basically why your code is not running is because you are returning chrome.local.storage which takes you out of the scope and get function never gets a chance to get executed. see the chrome API of how to do that it will be very similar to angular's $http service
if you uncomment return before the get , how do you except get call to be made??
basically you are coming out of function whenever you give return 'something'
in angular js you can call the then function using the following syntax
$http.get(url).then(function(response){
//put your callback code here
})