1

Apologies if this is obvious I am a bit of an Angular\Javascript noob. I have the following service:

MyApp.service('ClientService', function ($http, $q, SharedData) {

    this.get = function () {
        var deferred = $q.defer();
        $http.get("/api/Client/")
            .success(function(data, status) {

                deferred.resolve(data);
            })
            .error(function(data, status) {
                deferred.reject(data);
            });

        return deferred.promise;
    };

    this.setCurrentClient = function (clientToSelect) {
        var deferred = $q.defer();
        var getCurrentClient = this.get();

        $http({ method: "POST", url: "/api/Client", data: clientToSelect })
            .success(function (data, status) {

                //Get the full selected client and all its properties rather than the list version
                getCurrentClient.then(
                     function (client) {
                         setCurrentClient(client);
                         setCurrentPeriod(client);
                     },
                     function (data) {
                         //uho something broke.
                     });

                deferred.resolve(data);
            })
            .error(function (data, status) {
                deferred.reject(data);
            });

        return deferred.promise;
    }

    .....
});

In the this.setCurrentClient function I make a call to the backend via $http and on its asynchronous successful return I call the get function via a variable getCurrentClient. I originally tried to call get() or this.get() directly and neither worked. The context in the .success callback function seems to be the global window context not the service context. The above solution seems a little messy to me. Is there a better way to get the service context and call get() rather than setting a variable with the method (var getCurrentClient = this.get()) and then calling it (getCurrentClient.then()) ? A little lost with javascript\angular scope and contexts...

sarin
  • 5,227
  • 3
  • 34
  • 63
  • Have you looked at the $resource service? It seems like that is what you're really after? – Patrick May 27 '15 at 09:06
  • This is pure JavaScript scoping. Nothing related to Angular scoping. You need to save the scope reference and should access methods from the saved reference. `var self = this; self.setCurrentClient();` Else you should use https://docs.angularjs.org/api/ng/function/angular.bind – Vigneswaran Marimuthu May 27 '15 at 09:06
  • I don't have an issue with calling the backend service via $http. I believe using $resource does roughly the same but for RestFul services which we don't really use. The Async callbacks are the same. @VigneswaranMarimuthu I think that was essentially what I ended up with i.e. saving the outer scopes get() method in a variable to call in the inner function. I don't really understand why I have to do it? Why can't I just access the outer scope? – sarin May 27 '15 at 09:13
  • That's how angular `service` works, by instantiating the passed constructor function. If you have used angular `factory`, you won't have problem with scoping. Both creates `service` but in a different way. – Vigneswaran Marimuthu May 27 '15 at 09:27
  • as i mentioned in my answer you can skip this key word to in service if you want to use method inner same service, but if you want to access them from controller then you can pass your function to Service scope like this.myFunction = myFunction; and then you can use myFunction inside service without this keyword or setting a variable to call your function. – Jorawar Singh Jul 30 '16 at 19:39

3 Answers3

0

I believe you don't need to use "this" in your service, you can just declare your function as function get() { ... and then, in the callback in setCurrentClient, call:

var getCurrentClient = get();

However, if you do really need the "this", a common pattern is using var self = this; or something like that - see this discussion.

(as an aside, I would also recommend renaming your function and variables to have var clientPromise = getCurrentClient(); for better readability.)

Community
  • 1
  • 1
Emile
  • 2,946
  • 2
  • 19
  • 22
0

I would say use angular factory in this case.

MyApp.factory('ClientService', function ClientFactory($http, $q, SharedData) {

    function get() {
        var deferred = $q.defer();
        $http.get("/api/Client/")
            .success(function(data, status) {

                deferred.resolve(data);
            })
            .error(function(data, status) {
                deferred.reject(data);
            });

        return deferred.promise;
    };

    function setCurrentClient(clientToSelect) {
        var deferred = $q.defer();
        var getCurrentClient = get();

        $http({ method: "POST", url: "/api/Client", data: clientToSelect })
            .success(function (data, status) {

                //Get the full selected client and all its properties rather than the list version
                getCurrentClient.then(
                     function (client) {
                         setCurrentClient(client);
                         setCurrentPeriod(client);
                     },
                     function (data) {
                         //uho something broke.
                     });

                deferred.resolve(data);
            })
            .error(function (data, status) {
                deferred.reject(data);
            });

        return deferred.promise;
    }

    .....
    // Expose the service methods
    return {
        get: get,
        setCurrentClient: setCurrentClient
        ...... (Expose what all methods you wanted to expose)
    };
});
Vigneswaran Marimuthu
  • 2,452
  • 13
  • 16
0

Here is how i would use service as you want..`When you will try to call this.get inside http request then this will look for get method in Window scope and if you print this keyword in console you can see there is no get method. This always refer to the Object where you are using this

    MyApp.service('ClientService', function ($http, $q, SharedData) {

                    var get = function () {
                        var deferred = $q.defer();
                        $http.get("/api/Client/")
                            .success(function (data, status) {

                                deferred.resolve(data);
                            })
                            .error(function (data, status) {
                                deferred.reject(data);
                            });

                        return deferred.promise;
                    };

                    var setCurrentClient = function (clientToSelect) {
                        var deferred = $q.defer();

                        $http({
                                method: "POST",
                                url: "/api/Client",
                                data: clientToSelect
                            })
                            .success(function (data, status) {

                                //Get the full selected client and all its properties rather than the list version
                                get().then(
                                    function (client) {
                                        setCurrentClient(client);
                                        setCurrentPeriod(client);
                                    },
                                    function (data) {
                                        //uho something broke.
                                    });

                                deferred.resolve(data);
                            })
                            .error(function (data, status) {
                                deferred.reject(data);
                            });

                        return deferred.promise;
                    }
                    this.get = get;
                    this.setCurrentClient = setCurrentClient;
                });)
            .error(function (data, status) {
                deferred.reject(data);
            });

        return deferred.promise;
    }
    this.get = get;
    this.setCurrentClient = setCurrentClient;
})
Jorawar Singh
  • 7,463
  • 4
  • 26
  • 39