Retrieve the error message from the service and pass it to the controller in AngularJS

Utilizing a factory to fetch rates via REST

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

A service that interacts with the factory to retrieve resource and obtain rate information, including any potential errors.

 .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
                }
            }
        }
    }]);

The controller invokes the service to access rates.

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

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

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

While rates are displayed correctly in the controller upon successful promise fulfillment, errors are not being passed from the service to the controller. (The REST URL was modified to trigger a 404 response). What is the issue here?

Answer №1

At the moment, the asynchronous call response is being returned from outside of the async function, which technically should not be done. Asynchronous code should always receive responses inside their promise/callback function.

In this particular case, however, it seems to be working because an object with its reference is being returned. Looking at the code below, the return statement carries the object reference of self.rates, so even if it's empty, it will be updated once self.rates is filled up. Therefore, there's no need to worry about the updation of rates. However, the same concept wouldn't work for errors since they are of primitive data type, such as var error = null, which means when returning a value, it would be null until the async response is complete.

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

To address this issue, you could also convert the error into an object type, so its reference is passed along with the reference object. For example, use var errors = [] and push the error message into that array using .push when an error occurs.


However, I wouldn't recommend the above approach, as I'd suggest utilizing the promise pattern and maintaining a proper code call stack. Essentially, you should return a promise from the search method and then use the .then function to wait for resolving 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;
  });
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"Rotating the TransformControl in threejs: A step-by-step guide

When the object attached to the transform control rotates, I want the transform control itself to rotate as well. Before the rotation: https://i.sstatic.net/yjTue.png After the rotation: https://i.sstatic.net/2opuU.png As shown in the image, before th ...

Tips for transferring a data table (an object) from a JavaScript file to Node.js

On my HTML page, there is a table displaying student names and information, along with controls to manage the table. I created a save button to save this table as an object named SIT in my JavaScript code. I was able to manually save this table in MongoDB ...

JS animation triumphant

I have developed an app that utilizes a checkbox to control the appearance of an overlay on a screen. To ensure smooth transitions, I have incorporated animations into the process. #overlay{ position:absolute; height: 100vh; width: 100vw; ...

What regular expression should be used to meet the following requirement in JavaScript?

Criteria: Find words that begin with 'a' and end with 'b', with a digit in the middle, but are not on lines starting with '#' Given string: a1b a2b a3b #a4b a5b a6b a7b a8b a9b Expected output: a1b a2b a3b a7b a8b ...

What is the reason for the value of an object's key becoming undefined when it is set within a loop?

I've always wondered why setting a certain object's key as its own value in a loop results in undefined. Take this code block, for example: var text = 'this is my example text', obj = {}, words = text.split(' '); for (i = ...

Duplicate the canvas onto a new canvas

One of the functions I am using involves copying an old canvas to a new canvas. Here is the code snippet for this functionality: function cloneCanvas(oldCanvas) { //create a new canvas var newCanvas = document.createElement('canvas&a ...

Toggle button in React following a list iteration

Upon receiving data from an API call to Google Books, I want to hide the description paragraphs and implement a toggle button using the "hidden" CSS class from Tailwind CSS. Currently, I am just logging the elements on the "view description" button and uns ...

Assign individual heights to multiple iFrames according to their content's height

Dealing with multiple iframes on a single page. Each iframe is sourced from my domain. The goal is to automatically calculate and set the height of each iframe on the page. The current code sets all iframe heights to match that of a specific iframe: fun ...

Guide to utilizing import and export features in node.js

My issue involves two specific files: The first file, app.js The second file, module.js In app.js, there is an expression that looks like this: import 'foo' from './module' //use foo.. Meanwhile, module.js contains the following: ...

Using AngularJS to incorporate personalized font icons

Looking to create a custom font icon library similar to "Font Awesome" for my AngularJS project, as using fonts instead of images is more versatile across devices. Is there a way to achieve this? I have generated a font in .ttf and .svg formats with my ...

What could be causing the issue with loading data into my MongoDB collection?

Here is the content from my mongo database: https://i.sstatic.net/Z5PVv.png When I use app.post to insert the data, after submitting I can see the object with the dates in the console.log. However, when I try to use create function, it only displays "nul ...

Displaying an HTML string on a webpage

I am developing a user dashboard using Django for a Python-based web application. This web application generates emails, and the HTML content of these emails is stored in a file (and potentially in a database table as well). As part of the dashboard's ...

The jQuery .click() function is not triggering when clicked

$("#backButton-1").click(function() { $("#form-2").empty(); $("#form-1").show(); }); I am experiencing trouble with this code snippet. The form-1 element is hidden, and the backButton-1 is created after the end of for ...

Guide to implementing PCF (SOFT) shadows with three.js

Is it possible to apply the PCF (SOFT) shadow type, like the one found in the Three.js online editor, to your renderer using javascript code? https://i.sstatic.net/x0QmH.png ...

What's causing ng-show to malfunction in IE11 on AngularJS?

I am experiencing a strange issue with my code - ng-show works perfectly fine on Firefox, but not on IE 11. <div ng-show="isExist" class="panel panel-default"> Here is the relevant code snippet from the controller: $scope.isExist = false; if(user ...

Issue with RN-fetch-blob regarding base64 encoding specifically on Android devices

I've encountered an issue in React Native where I'm trying to download a base 64 string from an API and display it as a PDF on mobile devices. The problem arises when using the code on Android, as it returns a 'bad base 64' / invalid P ...

What could be causing this issue to not function properly in JavaScript?

Here is a JavaScript code snippet that I am working on: var inx=[2,3,4,5]; var valarray=[]; for (i=0; i<inx.length; i++) { valarray[i]==inx[i]; } for (i=0; i<inx.length; i++) { var posi=inx.indexOf(3); var valy=valarray[posi-1]+1; v ...

What's the best way to adjust the width of the <Input> component in Reactstrap?

How can I adjust the width of an input element in Reactstrap to be smaller? I've attempted to set the bsSize to small without success <InputGroup> <Input type="text" name="searchTxt" value={props.searchText ...

Why does my JavaScript file fail to retrieve the model.findByPk() method with the parameter "/:id"?

When attempting to retrieve items from the database based on their id, I am encountering an issue where Insomnia is returning an empty object. Specifically, in the code snippet below, my goal is to fetch a category by its ID while also retrieving any assoc ...

The data insertion query in MYSQL seems to be malfunctioning

I am facing an issue with inserting data from a form into a database table named "sumation". Despite using PhpStorm IDE, I am getting errors indicating that no data sources are configured to run the SQL and the SQL dialect is not set up. Can anyone help ...