1

I have such working code:

Service (factory?):

myApp.factory('MyService', ['$q','$resource', 'MyResource',
    function ($q, $resource, MyResource) {

        return {
            getRoles: function () {
                return MyResource.getRoles(); //MyResource makes API calls using $resource 
            } } });

Controller:

$scope.Roles = MyService.getRoles();
$scope.Roles.$promise.then(function () { $scope.RolesCount = $scope.Roles.length; });

What I'd like to do is to create such function in MyService that will return number of roles once getRoles is resolved so I can use it in controller like this:

$scope.RolesCount = MyService.getRolesCount();

and then in html

{{RolesCount}}

Unfortunately, I have no idea how to do this since my getRolesCount() method needs to return something so I can't use $promise.then() inside MyService. I'll try to update my question's title once I come up with something more accurate.

Kostrzak
  • 161
  • 4
  • 19
  • You should redefine getRoles action with `actions` option and provide transformResponse, something like this. – Estus Flask Oct 04 '17 at 17:23
  • Yeap but it sounds like manipulating on Resource/Repository layer. What if I want to process returned data on Service layer (isn't it what it is for?) and then return result to controller (as object reference same way as $resource does it)? – Kostrzak Oct 04 '17 at 21:45
  • Yes, a service is more suitable place. But in your case none of these approaches work because `then` not just transforms the response but unwraps its value. Moreover, you don't really need to do this with resources. – Estus Flask Oct 04 '17 at 23:00

1 Answers1

0

If server response needs to be transformed in a service, then then should be moved there. However, it's not practical or possible if then is supposed to unwrap a promise and assign a value to scope, like in the code above.

$resource returns an object that is filled on promise resolution. The way a resource is supposed to be used in view is:

{{Roles.length}}

When an object is updated, it will be updated in view, too. Assigning the value to another variable is inefficient.

It's impossible to do something like

$scope.RolesCount = MyService.getRolesCount();

because getRolesCount is asynchronous, and the value it resolves with is scalar. It is possible to flatten it with `async..await, (TypeScript or ES2017), but will require additional measures to synchronize control flow with AngularJS digests, as explained in this answer.

Fergus
  • 2,821
  • 2
  • 27
  • 41
Estus Flask
  • 206,104
  • 70
  • 425
  • 565