Defining the Angular service scope of a service call

I am confused by why I cannot get this service call to be executed as needed. console.log within the scope of definitionsService.get promises is what I expect (the object I want to return to). However, console.log will be undefined right before I return defs , which of course means that my return value is undefined. What am I missing?

 function getDefinitions() { var defs; definitionsService.get().$promise.then(function(data) { console.log(data); defs = data; console.log(defs); }); console.log(defs); return defs; }; 

I changed the above:

 function getDefinitions() { var defs = $q.defer(); definitionsService.get().$promise.then(function(data) { defs.resovle(data); }); return defs.promise; }; 

for the answer below.

I also changed the way I call this method for the same answer as follows:

 function detail(account) { getDefinitions().then(function(definitions) { var key = angular.isDefined(definitions.ABC[account.code]) ? account.code : '-'; return definitions.ABC[key].detail; }); } 

Then in my controller, I try to do the following:

 var getAccounts = function() { playersService.getAccounts({ playerId: playerId }).$promise.then(function(accounts) { for (var i = 0; i < accounts.length; i++) { accounts[i].detail = utilitiesService.detail(accounts[i]); } vm.accounts = accounts; }); }; var init = function() { getAccounts(); }; init(); 

My problem is that accounts[i].detail sequentially undefined .

+5
source share
2 answers

Welcome to the world of asynchronous calls.

If you call an asynchronous call inside getDefinitions (from definitonsService), you should assume that getDefinitions () is also asynchronous. This means that you cannot just return defs.

When you print defs before returning it, the asynchronous service call has not yet completed.

defs should also be an object of promise. Then you can return it the same way you do, but the method calling it should also use it with .then (function (defs) ...

Or in code form:

 function getDefinitions() { var defs = $q.defer(); definitionsService.get().$promise.then(function(data) { defs.resovle(data); }); return defs.promise; }; 

And anyone who calls getDefinitions() :

 getDefinitions().then(function(defs) { // do something with defs... } 

The answer to the question after editing:

The problem is again related to the asynchronous nature inside the getAccounts method. utilitiesService.detail is an asynchronous method. This way you are actually assigning promises, not values, to the [i] .detail accounts.

Since each account entails an asynchronous call, using $ q.all seems like a good idea:

 var promises = []; for (var i = 0; i < accounts.length; i++) { promises.push(utilitiesService.detail(accounts[i])); } $q.all(promises).then(function(values)){ // you should have all the account details inside 'values' and can update vm.accounts } 

remember - receiving a promise is synchronous. Getting a value that promises ... well, promises to get you is asynchronous.

+2
source

The problem is that you return defs before the promise has been resolved, and defs === None .

You can solve this problem by changing the code a bit:

 function getDefinitions() { return definitionsService.get().$promise.then(function(data) { return data; }); }; 
0
source

All Articles