Dealing with Restangular errors: a guide on sending a custom object to a controller unaware of Restangular

I'm facing a challenge with my current approach, possibly due to my limited understanding of Angular promises versus Restangular promises. I have developed an AngularJs application using TypeScript, although the usage of TypeScript is not crucial in this context and the same principles apply to any JavaScript project. Here's an overview of the components involved:

  1. Controller: This component receives a service injection through which it can send a POST request to an API.
  2. Service: This service encapsulates Restangular functionalities. The main idea behind this service is to shield the controller from directly interacting with Restangular. It provides a method that takes an object as input and returns an Angular promise.

    export interface IRegistrationService {
        addRegistration(model: registration.BusinessRegistration): ng.IPromise<void>;
    }
    
  3. Restangular error interceptor: Responsible for handling HTTP responses with a status code of 400, which typically indicate validation errors received from the API. It transforms these errors into a custom object. The goal is for the controller to either successfully save an item (by utilizing the service) or receive a validation error reported by this interceptor.

This is what I've implemented so far:

The Restangular error interceptor:

restangularProvider.setErrorInterceptor((response: restangular.IResponse, deferred: ng.IDeferred<any>, responseHandler: any) => {
     if (response.status === 400) {
         let validationError: myTsd.IApiValidationErrors = getAsValidationError(response.data);
            // How can I pass this validationError as an errorCallback to the controller?
            //deferred.notify(validationError); 
            //deferred.reject(validationError); //this breaks the chain
            //return true; // if error is not handled. But where should I store the validationError?
            //return false; // if error is handled. But where should I store the validationError?
        }
    });

The service abstracting the controller from Restangular specifics: Note that this service should return an Angular promise instead of a Restangular promise.

public addRegistration(model: registration.BusinessRegistration): ng.IPromise<void> {
     return this.restangular.all("registration")
              .post<registration.BusinessRegistration>(model)
                .then(() => {
                    console.log("Registration posted successfully");
                }, (error: any) => {
                    //How do I make this object available in the controller's errorCallback?
                }, (notify: any) => {
                    //How do I make this object available in the controller's errorCallback?
                });
 }

The controller utilizing the service without direct knowledge of Restangular:

//public static $inject = ["app.services.RegistrationService"];
//.. controller code
this.registrationService.addRegistration(this.model)
      .then(() => {
            console.log("Model successfully posted to remote API")
       }, (error: myTsd.IApiValidationErrors) => {
            //I need access to the validation error object here
            console.log(error);
       });

How should I properly chain everything together? My main requirements are:

  • The logic for creating the custom object should reside in a central place like the setErrorInterceptor, capable of distinguishing between HTTP responses with a status code of 400 and others. If the response does not fall within the 2xx or 400 range, it should handle the error internally or pass it to the Restangular-utilizing service.
  • The service employing Restangular should enable the controller to succeed in saving an item or receive a callback error containing the custom validation error object, effectively shielding the controller from unnecessary complexities.

Thank you in advance!

I'm finding the documentation somewhat challenging to comprehend here. I wonder if there are alternative actions aside from notifying or rejecting that could be taken.

Answer №1

Restangular's method .setErrorInterceptor() operates in a unique manner, with limitations on its functionality that may not align with your expectations.

While it is possible for the interceptor to detect specific error codes like 400 and perform actions accordingly, its options are limited to either blocking or not blocking the promise chain.

  • Non-blocking behavior allows the promise chain to continue as usual without interference.
  • Blocking behavior halts both the error and success paths of the promise chain.

It's important to view .setErrorInterceptor() as a "selective blocker" rather than a typical filter or catch mechanism. Contrasting it with the behavior of promise.catch(), where errors can be handled in various ways such as converting them to success or throwing new errors.

  • Unlike .setErrorInterceptor(), promise.catch() offers more flexibility in managing error states within the promise chain.

In scenarios where you need more control over handling specific conditions like a "400" error, consider using a named catch handler function instead. This approach can provide the desired features without being restricted by the limitations of .setErrorInterceptor().

Remember that compatibility between Angular promises and Restangular should not pose significant issues when used together seamlessly.

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

The functionality to verify the presence of a child element is not functioning correctly when using

Trying to determine the existence of a child, I have created a new Firebase list observable and also attempted with an object observable. Upon creating the observable, I verify if it exists or not; however, it always returns false. Database Structure: {R ...

Having trouble administering $httpBackend injection

Currently, I am utilizing Angular 1.5 to create mocked services for my current project by referring to this helpful example: https://embed.plnkr.co/qsmx8RUmQlXKkeXny7Rx/ Here is a snippet of the code that I have developed so far: function() { 'use ...

Deny access to the viewing feature for unauthorized users

Objective: To restrict access to the profile page only for logged-in users. The authentication is done through mongodb and passport-local. Existing Code: Below is the express route used to verify if the request is authenticated. app.get('/loggedin ...

Performing updates on Meteor.users collection while handling a promise rejection (leveraging fcm-push with Meteor)

My current project involves the use of an NPM package called fcm-push in order to send FCM notifications to different mobile devices based on specific messages. Everything works fine when the message is successfully sent, but if the sending fails due to th ...

What is the best way to transmit data to the server using angular.toJson?

I'm struggling to grasp the purpose of angular.toJson. I get that it converts to a JSON object... However, how do I send this object to the server? The server already provides a JSON object with 'GET' requests, but how can I utilize it for ...

Troubleshooting: Issue with auto height functionality in Angular's ui-grid

Utilizing angular's ui-grid to display records, I have a scenario where one product has 7 entries and another product has 200 entries. By default, the grid is set to display a maximum of 20 rows when there are more than 20 records. If there are less t ...

Angular Modal Service Unit Test Template for $uibModal

My service has a simple show() function that basically calls $uibModal with some configuration and returns the modal instance function customModalService($uibModal) { return { show(message) { return $uibModal.open({ bindToController: t ...

Tips for creating TypeScript Google Cloud Functions using webpack

I'm currently facing a challenge while coding a Google Cloud Function using TypeScript. The concept involves having handler functions defined for various Cloud Functions in separate files within the source repository, along with some code that is shar ...

Tips for preventing needless re-renders in React functional components when dealing with "static components"

In my React functional component, I have a feature that displays a list of tags and posts along with some static text and decorations. The currently selected tag is stored in a state using the useState hook. Posts are fetched through Apollo's useQuery ...

The AngularJS $filter(date) function is causing incorrect format outputs

Hey there! I've come across an issue with my AngularJS filter, where it's supposed to return a date in a specific format. However, when I try the following code: var input = '2015-08-11T13:00:00'; var format = 'yyyy MMM dd - hh:mm ...

A guide to accessing parent attributes in Vue3 using typescript

Within my child component, I am facing an issue where I need to access the parent object but the commented lines are not functioning as expected. The structure of AccordionState is defined below: export type AccordionKeys = | "open" | "disa ...

Choosing and Duplicating Text in Angular

I'm attempting to give the user the ability to select a paragraph and copy it by clicking a button. However, my current code is not working as expected. I initially tried importing directives but encountered errors, prompting me to try a different met ...

Using React Typescript to create a button component with an attached image

I am currently utilizing React with Typescript. How can I incorporate an image into my button? I've attempted to do so without any errors, but the button appears blank. What's the best way to style my button element using Emotion CSS in this ...

Creating a React component that allows for pagination using data fetched from a

I have a Spring Boot endpoint that retrieves and lists items from a database: @RequestMapping(method = RequestMethod.GET, value = "/task", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<?> processTask(@Valid TaskSearchP ...

Localhost server experiencing issues with uploading files through Express framework

I'm currently trying to integrate the ng file upload feature into my node application running locally on localhost. Following the example shown here, I encountered an issue when attempting to change the download directory. file.upload = Upload.upload ...

Setting a default checked radio button option in Angular

I'm looking to have a default radio button option checked, but so far my attempts with ng-model and ng-init haven't been successful. Here's my HTML: <div bindonce ng-repeat="row in results.favorites" style="padding: 0px 10px; white-spac ...

Angular JS: Saving information with a promise

One dilemma I am facing is figuring out where to store data that needs to be accessed in the final callbacks for an http request. In jQuery, I could easily handle this by doing the following: var token = $.get('/some-url', {}, someCallback); tok ...

The click listener triggers a single time when a render method is nested within it

When I have a click listener on a button that resets the innerHTML of a div with a render method, the listener fires every time I click if I take out the render function. However, if the render function is included, the listener does not fire multiple time ...

Utilizing React Router with the power of useCallback

My route configuration is set up as follows: const defineRoutes = (): React.ReactElement => ( <Switch> <Redirect exact from="/" to="/estimates" /> <Route exact path="/estimates" component={CostingPa ...

Seed Database for Protractor End-to-End Testing

I've been struggling to find a proper method for this, so I'm hoping someone can offer some suggestions. Is there a way to pre-populate the database with testing data prior to running an E2E Protractor test? Do people typically do this, or do th ...