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:
- Controller: This component receives a service injection through which it can send a POST request to an API.
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>; }
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.