0

I have a similar situation like in AngularJS : Initialize service with asynchronous data, but I need to inject my base service with asynchronous data into depend services. It looks like this:

Base service:

angular.module('my.app').factory('baseService', baseService);

baseService.$inject = ['$http'];

function baseService($http) {
    var myData = null;

    var promise = $http.get('api/getMyData').success(function (data) {
        myData = data;
    });

    return {
        promise: promise,
        getData: function() {
            return myData;
    }};
}

Dependent service (in which I inject base service)

angular.module('my.app').factory('depentService', depentService);

depentService.$inject = ['baseService'];

function depentService(baseService) {
    var myData = baseService.getData();
    ....

    return {...};
}

Route:

    angular.module('my.app', ["ngRoute"])
    .config(function ($routeProvider) {
        $routeProvider.when('/',
            {
                resolve: {
                    'baseService': function (baseService) {
                        return baseService.promise;
                    }
                }
            });
    });

But nothing happens, baseService.getData() still returns null (coz async api call still in progress). Seems like my ngRoute config is invalid, but I cant indicate any controller/template into it. How can I correctly resolve my baseService and get data in Depend service?

georgeawg
  • 48,608
  • 13
  • 72
  • 95
krabcore
  • 885
  • 2
  • 8
  • 22
  • Why not register the service with angular and then inject it into the component/controller where needed? Then just call the method to get the data as a promise. This would be the standard approach that most angularjs devs take and any experienced angularjs dev will be able to read your code (if done that way). – Igor Mar 27 '20 at 17:34
  • Igor, you totally right.your suggestion is right way to deveplop modern application. Currently all services returns objects with data, so I cant easily change it to promises. In this case I will need to change structure of whole legacy UI application (20+ controllers, 200+ service calls). This is unacceptable for me. – krabcore Mar 27 '20 at 21:56

1 Answers1

2

Dependent services should work with promises and return promises:

angular.module('my.app').factory('depentService', depentService);

depentService.$inject = ['baseService'];

function depentService(baseService) {
    ̶v̶a̶r̶ ̶m̶y̶D̶a̶t̶a̶ ̶=̶ ̶b̶a̶s̶e̶S̶e̶r̶v̶i̶c̶e̶.̶g̶e̶t̶D̶a̶t̶a̶(̶)̶;̶
    var promise = baseService.promise;
    
    var newPromise = promise.then(function(response) {
        var data = response.data;
        //...
        var newData //...
        return newData;
    }); 

    return newPromise;
}

To attempt to use raw data risks race conditions where the dependent service operates before the primary data returns from the server.

From the Docs:

The .then method returns a new promise which is resolved or rejected via the return value of the successCallback, errorCallback (unless that value is a promise, in which case it is resolved with the value which is resolved in that promise using promise chaining).

AngularJS $q Service API Reference - The Promise API

Community
  • 1
  • 1
georgeawg
  • 48,608
  • 13
  • 72
  • 95