0

Factory that gets the rates using REST

.factory('rateResource', ['$resource', function ($resource) {
    return $resource('/rates/:currency/:effectiveDate', {
        currency: '@currency',
        effectiveDate: '@effectiveDate'
    });
}])

Service that calls the factory to get resource and retrieve the rates and also errors if there are any.

 .service('RateService', ['rateResource', '$rootScope',
    function (rateResource, $rootScope) {
        var self = this;

        self.rates = [];

        self.search = function (baseCurrency, effectiveDate) {
            self.rates = [];
            var error = null;
            self.baseCurrency = baseCurrency;
            self.effectiveDate = effectiveDate;
            if (baseCurrency) {
                rateResource.query({currency: baseCurrency, effectiveDate: effectiveDate})
                    .$promise.then(function (rates) {
                        if (rates) {
                            angular.forEach(rates, function (rate) {
                                rate.maintTs = $rootScope.formatTimestampToHHMMSS(rate.maintTs);
                                rate.editable = false;
                                self.rates.push(rate);
                            });
                            self.processing = false;
                        }
                    }, function (response) {
                        self.processing = false;
                        error = 'Processing failed due to '+response.status;
                        console.log(error);
                    })
                return {
                    rates: self.rates,
                    errors: error
                }
            }
        }
    }]);

Controller calls the service for rates.

.controller('RateController', ['RateService',
    function (rateService) {
        var self = this;

        self.baseCurrency = rateService.getBaseCurrency();
        self.effectiveDate = rateService.getEffectiveDate();
        self.rates = rateService.getRates();

        //make the call from the controller
        self.search = function () {
            var response = rateService.search(self.baseCurrency, self.effectiveDate.yyyyMMdd());
            self.rateRecords = response.rates;
            self.errors = response.errors;
        }
    }])

rates are showing up fine in the controller after the promise is fulfilled. However, upon receiving errors, they are not getting transferred from service to controller. ( I changed the REST URL to make service return a 404 response ). What am I doing wrong?

5
  • you can not get self.rates value outside promise function..because they are filling up asynchronously. Commented Feb 11, 2016 at 20:04
  • self.rates is working fine for me; After the promise is fulfilled, I can see the rates in the display via the controller. The issue is with errors Commented Feb 11, 2016 at 20:27
  • Ohh.. self.rates working fine because you are passing self.rates reference.. what errors you are talking about..? Commented Feb 11, 2016 at 20:29
  • I would like to pass error = 'Processing failed due to '+response.status; message to the controller. I simulated 404 by making a request to an invalid url, but, the error is not being sent to the controller. Commented Feb 11, 2016 at 20:30
  • look at the answer which I've added. Commented Feb 11, 2016 at 20:43

1 Answer 1

1

Currently you are returning asynchronous call response from outside of async function, you shouldn't do that technically. Asynchronous code always get there responses inside their promise/callback function.

But in your case it is working because you are returning object with it reference. If you look at below code, return statement has carried self.rates object reference, so while returning even if it is blank, it is going to get updated value once self.rates gets filled up. So then you don't need to worry about the rates updation. But same thing for error would not work because it is of primitive datatype like var error = null, so when you are returning value it would be null(as async response haven't completed).

return {
     rates: self.rates, //passed by reference
     errors: error //passed by primitive type
}

So for solving this issue you could also make the error to an object type, so that it reference will get passed with reference object, like var errors = [] & when error occur push the error message into that array using .push


But I'd not recommend above way to go for, I'd rather take use of promise pattern and will maintain proper code call stack. Basically for that you need to return promise from search method & then put .then function to wait till resolve that function.

Service

.service('RateService', ['rateResource', '$rootScope',
    function(rateResource, $rootScope) {
      var self = this;
      self.rates = [];
      self.search = function(baseCurrency, effectiveDate) {
        self.rates = [];
        var error = null;
        self.baseCurrency = baseCurrency;
        self.effectiveDate = effectiveDate;
        if (baseCurrency) {
          return rateResource.query({
            currency: baseCurrency,
            effectiveDate: effectiveDate
          })
            .$promise.then(function(rates) {
            if (rates) {
              angular.forEach(rates, function(rate) {
                rate.maintTs = $rootScope.formatTimestampToHHMMSS(rate.maintTs);
                rate.editable = false;
                self.rates.push(rate);
              });
              self.processing = false;
            }
            //returning object from promise
            return {
              rates: self.rates,
              errors: error
            }
          }, function(response) {
            self.processing = false;
            error = 'Processing failed due to ' + response.status;
            console.log(error);
            //returning object from promise
            return {
              rates: self.rates,
              errors: error
            }
          })
        }
      }
    }
])

Controller

//make the call from the controller
self.search = function() {
  var response = rateService.search(self.baseCurrency, self.effectiveDate.yyyyMMdd()).then(function() {
    self.rateRecords = response.rates;
    self.errors = response.errors;
  });
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.