0

I work on my angularjs project. I created this service:

(function () {
    "use strict";

    angular.module("manageItems").factory("manageItemsService", ["$http", "config", manageItemsService]);

    function manageItemsService($http, config) {
        var service = {
            getNewItems: getNewItems,
        };
        return service;

        function getNewItems(session, mapName) {
            return $http.get(serviceUrl + 'getNewItems/' + session + "/" + mapName);
        }

    }
})();

And here how I call the service from controller:

function getNewItems() {
    manageItemsService.getNewItems(mapguideService.mapName, mapguideService.sessionId).then(function (result) {
        self.currentItems = result.data;
    })
}

I need to make service to delay while the response returned.

How can I change servicefunction to make it wait until self.currentItems property is populated by data?

georgeawg
  • 48,608
  • 13
  • 72
  • 95
Michael
  • 13,950
  • 57
  • 145
  • 288

3 Answers3

1

First I need say that http requests are actually performed asynchronously so as not to stop the application while the result is returned.

So you have two options, use the angular pattern to adjust your method in order to treat the result, so you must pass a callback function to the service, so that the service, not the controller make the association. It would be something like:

Service:

 (function () {
        "use strict";

        angular.module("manageItems").factory("manageItemsService", ["$http", "config", manageItemsService]);

        function manageItemsService($http, config) {
            var service = {
                getNewItems: getNewItems,
            };
            return service;

            function getNewItems(session, mapName, callback, errorCallback) {
                $http.get(serviceUrl + 'getNewItems/' + session + "/" + mapName).then(callback, errorCallback);;
            }

        }
    })();

Controller:

function getNewItems() {
    manageItemsService.getNewItems(mapguideService.mapName, mapguideService.sessionId, function (result) {
        //this callback will be called asynchronously when the response is available
        self.currentItems = result.data;
    }, function(error) {
        // called asynchronously if an error occurs
        // or server returns response with an error status.
    })
}

The second option is to totally not recommended, inserting a loop while the result is expected... (to bad)

I hope I have helped!

  • 1
    See [Why are Callbacks from Promise `.then` Methods an Anti-Pattern](http://stackoverflow.com/questions/35660881/why-are-callbacks-from-promise-then-methods-an-anti-pattern). – georgeawg Mar 14 '17 at 03:38
0

Then you could be put up .then on getNewItems $http call. And based on retrieved response data, decide whether to return data or call another service method.

function anotherFunction(){
    return $http.get(url);
}

function getNewItems(session, mapName) {
    return $http.get(serviceUrl + 'getNewItems/' + session + "/" + mapName).then(function successCallback(response){
       var data = response.data;
       //call another function if data is empty
       if(!data.length)  
         return anotherFunction(); //make sure another function should return promise
       return data;
    });
}
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • Thanks for post.What if I need to make 3 calls?I mean if first is empty make second if seci=ond is empty make third.I don't think it's good practice – Michael Mar 13 '17 at 15:33
  • 2
    this is how I handle it when I want to process intermediate step before service respond.. using & extending promise chaining is good way to deal with such scenario. I don't think so its bad practice(let me know if you find any reference where its states mentioned is bad practice), Thanks ;) – Pankaj Parkar Mar 13 '17 at 16:00
0

What the code needs to do is chain promises.

To make the getNewItems function chainable, return the derived promise:

function getNewItems() {
    //vvvv RETURN promise
    return manageItemsService.getNewItems(mapguideService.mapName, mapguideService.sessionId)
      .then(function (response) {
        self.currentItems = response.data;
        //RETURN value to chain
        return response.data;
    });
};

Then use the returned promise to chain more operations:

getNewItems().then( function(currentItems) {
   //Evaluate current Items
   if ( ok ) {
       return "DONE";
   } else {
       //RETURN to chain something else
       return getOtherItems();
   };
}).then( function(otherItems) {
   if (otherItems == "DONE") return;
   //ELSE
   self.otherItems = otherItems;
   //Do further chaining
});

Because calling the .then method of a promise returns a new derived promise, it is easily possible to create a chain of promises.

It is possible to create chains of any length and since a promise can be resolved with another promise (which will defer its resolution further), it is possible to pause/defer resolution of the promises at any point in the chain. This makes it possible to implement powerful APIs.

— AngularJS $q Service API Reference - Chaining Promises

georgeawg
  • 48,608
  • 13
  • 72
  • 95