1

I am having some problems with executing some tasks before my service is initialised and it's methods used. Some context:

I am producing an application which uses REST to communicate with 2 different backend systems (the reason for this is that if our client upgrades in the future it will still work). These backend systems have slightly different paths for the same REST calls.

To know which calls to use I thought a solution might be to call one test endpoint which exists in one, but not the other, and depending on the response code received, set a variable which is the beginning of the URL. e.g. /rest/services/StartpointService/.

All the REST calls are in a single factory and I tried something like this:

angular.module('myApp.services', [])
.factory('myServices', [
    '$http',
    '$q',
    function($http, $q) {

        //test function, if success we are using 1 backend, if fails, we use the other
        var loginTest = function() {

            var deferred = $q.defer();

            $http( {

                method: 'POST',
                url: '/um/login?um_no_redirect=true'

            })
            .success(function(data, status, headers, config) {

                deferred.resolve(status);

            })
            .error(function(data, status, headers, config) {

                deferred.reject(status);

            });
            return deferred.promise;

        };


        var url;

        loginTest()
        .then( function(response) { //if backend1

            if(responseCode === 200) {
                url = '/rest/services/etc/etc' //set the URL
            }

        },
        function(errorCode) {   //If backend2


            if(errorCode === 404) {

                url = '/LCConnector/rest/services/etc/etc';

            }

        });



        var service = {

            realCall : function() {

                                    //use 'url' variable in the $http call

                            }
                    }

                    return service;

           }]);

Obviously as the loginTest is asyncronous, the service is injected into my controller and is called before url is set.

I have looked into running in a config or run block when the app is first initialised but can't quite understand how to get the variable out.

If i can give anything further details, please let me know!

Regards,

Augier

Augier
  • 311
  • 2
  • 13

2 Answers2

2

If this check is required before the application is initialized you can manually bootstrap your application after the Ajax call. Inside of your fail() or done() call backs you can alter the module config to reflect the url you need. From there you can easily inject your config into any service that requires this url.

example on jsfiddle

<div ng-controller="MyCtrl">{{url}}</div>


//if you chanée this url to /echo/fail and url will now be url1
var urlToCheck = '/echo/json/';

var myApp = angular.module('myApp', []);

myApp.controller("MyCtrl", ["$scope", "config", function ($scope, config) {
    $scope.url = config.url;
}]);

$.ajax({
    url: urlToCheck
}).fail(function () {
    myApp.constant('config', {
        url: '/fail-url'
    });
}).done(function () {
    myApp.constant('config', {
        url: '/done-url'
    });
}).always(function () {
    angular.bootstrap(document, ['myApp']);
});
Community
  • 1
  • 1
Mark Coleman
  • 40,542
  • 9
  • 81
  • 101
  • 1
    Thanks for this Mark, very useful and works precisely how I wanted. For a bonus point, could you help me with getting my tests to run? I am using Karma and this has broken them. I have added app/index.html to the files to load but it is still saying it can't find the module. – Augier Feb 21 '14 at 14:52
0

You could take advantage of $routeProvider, which allows you to delay your controller instantiation until your promise has been resolved.

$routeProvider exposes a method called resolve for that purpose. See the AngularJS doc:

http://docs.angularjs.org/api/ngRoute.$routeProvider

Additional information in this excellent SO question:

AngularJS : Initialize service with asynchronous data

Highly recommended.

Community
  • 1
  • 1
roland
  • 7,695
  • 6
  • 46
  • 61