0

I have a factory in Angular, where I want to add an alert if an error is encountered.

Here's my call to the factory:

gradeService.assignGrade(requestData).then(Controller.populateResponseObject, Controller.error);

where Controller just a this for the current controller: var Controller = this.

When I try to trigger the error in the UI, a 500 Server Error is encountered(as expected), but it goes to populateResponseObject, not to error. How to I get the service to return error?

Here's the service code:

app.factory('gradeService', function ($http) {

    var baseUrl = "http://localhost:8080";

    var add = function (request) {
        var requestUrl = baseUrl + "/grade/new";

        return $http.post(requestUrl, request)
        .then(function (responseSuccess) {
            return responseSuccess.data;
        },
        function (responseError) {
            return responseError.data;
        });
    };

    return {
        assignGrade: add
    };
});

Here's the relevant error code:

Controller.error = function (error) {
    // ... some code
    else if(error.status === 500) {
        if(error.exception === "org.springframework.dao.DataIntegrityViolationException") alert("Error: this person has already been graded for this month. Grade was not saved.");
        else if(error.exception === "java.sql.SQLException") alert("Error establishing connection with database. Please try again later.");
        else alert("Error: " + error.message + ": Generic Server Error.");
    }
};

I'm using Spring for the backend code.

Any help?

cst1992
  • 3,823
  • 1
  • 29
  • 40
  • have you tried: `return $http.post(requestUrl, request) .success(function (responseSuccess) { return responseSuccess.data; }).error(function (responseError) { return responseError.data; }); };` – Rarepuppers Mar 01 '16 at 07:25
  • @comoss That's deprecated. – cst1992 Mar 01 '16 at 07:49
  • you're right. https://github.com/remcohaszing/eslint-plugin-angular/commit/aa621d4de17f86319780cf4850f4cbc4522bac20 – Rarepuppers Mar 01 '16 at 07:52
  • 1
    @comoss The `.success` and `.error` methods **ignore** returned values. This is one of the reasons they were deprecated. – georgeawg Mar 01 '16 at 08:33
  • To future readers: Doing a `console.log()` on your returned value in your controller should clarify what's happening here. If you get a `Promise {...}` in the log, then the promise was returned. If, however, you resolve the promise in the service, then you'll just get an `Object {...}`, and doing `.then()` on it again will give you 'not a function' errors(obviously). – cst1992 Dec 20 '16 at 13:17

4 Answers4

1

Your problem is that you do not return a promise in your assignGrade()/add() function but the response data. That means that there will be no correct promise handling made by Angular.

Just do the following, then your handling should work fine:

app.factory('gradeService', function ($http) {

    var baseUrl = "http://localhost:8080";

    var add = function (request) {
        var requestUrl = baseUrl + "/grade/new";

        return $http.post(requestUrl, request);
    };

    return {
        assignGrade: add
    };
});
cst1992
  • 3,823
  • 1
  • 29
  • 40
Moritz
  • 174
  • 4
  • If you want to handle the results outside, then not :) .then() will resolve your promise, so there will be no way for you to handle it afterwards. The other possibility would be to handle your error in the factory. Then you need to execute your success/error handler where you currently return *.data... – Moritz Mar 01 '16 at 07:51
  • Thanks for your help. – cst1992 Mar 01 '16 at 08:52
  • BTW, are there only special types of methods( such as `post`) for which I don't use `then`? Doing this for `get` resulted in the service returning `undefined`. – cst1992 Mar 03 '16 at 07:35
  • .then () is the function getting executed when a promise is resolved. Since your $http.post() method returns a promise, you can call then() on it. If you already resolve it before returning, then you will get the error. – Moritz Mar 06 '16 at 13:05
1

To chain an error, throw it back to the onRejected function.

app.factory('gradeService', function ($http) {

    var baseUrl = "http://localhost:8080";

    var add = function (request) {
        var requestUrl = baseUrl + "/grade/new";

        return $http.post(requestUrl, request)
        .then(function onFulfilled(responseSuccess) {
            return responseSuccess.data;
        },
        function onRejected (responseError) {
            //to chain rejection throw it
            throw responseError;
            //Not return
            //return responseError.data;
        });
    };

    return {
        assignGrade: add
    };
});

Returning something from an onRejected handler converts the derived promise to a fulfilled promise.

For more information, see Angular execution order with $q.

Community
  • 1
  • 1
georgeawg
  • 48,608
  • 13
  • 72
  • 95
0

You have to handle promise in controller not in service.

app.factory('GradeService', function ($http) {
    var obj = {}
    var baseUrl = "http://localhost:8080";

    obj.add = function (request) {
        var requestUrl = baseUrl + "/grade/new";

        return $http.post(requestUrl, request);
    };

    return obj;
});

I think the above code will give solve your issue.

Raja Sekar
  • 2,062
  • 16
  • 23
0

First, modify the factory:

app.factory('gradeService', function ($http) {

    var baseUrl = "http://localhost:8080";

    var add = function (request) {
        var requestUrl = baseUrl + "/grade/new";

         return $http.post(requestUrl, request);
    };

    return {
        assignGrade: add
    };
});

Then, call the factory like this:

gradeService.assignGrade(requestData).then(function(success) {
    // Some success code...
}, function(error) {
    // Some error code...
});
ddepablo
  • 677
  • 1
  • 5
  • 16