How to correctly override `errResponse` which is passed to the `catch(function(errResponse){` function?

淺唱寂寞╮ 提交于 2019-12-12 02:38:47

问题


This is my controller:

angular.module("AuthenticationApp", ["BaseApp"])
    .controller("MainCtrl", ["$http", "$window", "BaseService", function($http, $window, BaseService) {
        var self = this;

        self.add = function() {
            BaseService.add.user(self.user)
                .catch(function(errorResponse) {
                    self.cerrorMessages = errorResponse.data;
                });
        };

This is my BaseApp / factory:

angular.module("BaseApp", [])
    .config(['$httpProvider', function($httpProvider) {
        $httpProvider.defaults.xsrfCookieName = 'csrftoken';
        $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
    }])

    .factory("BaseService", ["$http", "$window", function($http, $window) {
        var self = this;

        self.add = {
            user: function(user) {
                $http.post("/users/", user)
                .then(function(response) {
                    $http.post("/api-auth/login", user)
                    .then(function(response) {
                        $window.location.href = "/";
                    });
                // if there are errors, rewrite the error messages
                }).catch(function(response) {
                     for (prop in response.data) {
                         if (prop == "email") {
                             response.data[prop] = "Please enter a valid email address.";
                         } else if (prop == "username") {
                             response.data[prop] = "Please enter a valid username";
                         }
                     }
                });
            }
         };

When I try to run this code and call self.add() on my controller, I get an error saying TypeError: Cannot read property 'catch' of undefined pointing to the line .catch(function(errorResponse) { in my controller. I'm guessing this is because there is no then() function.

What should I do to properly override the errResponse parameter which is passed to the controller's .catch() function (without having a .then() function because nothing is needed to be done if it is successful)?


回答1:


When I try to run this code and call self.add() on my controller, I get an error saying TypeError: Cannot read property 'catch' of 'undefined' pointing to the line .catch(function(errorResponse) { in my controller. I'm guessing this is because there is no then() function.

That is an erroneous guess. The self.add() returned undefined because the function omitted a return statement. When functions omit return statements, they return the primitive value undefined. There is neither a .then method nor a .catch method on the primitive undefined. Thus the TypeError: Cannot read property 'catch'.

It is important to return the httpPromise:

user: function(user) {
    //vvvv RETURN the promise
    return $http.post("/users/", user)
      .then(function successHandler(response) {
        //vvvv RETURN to chain
        return $http.post("/api-auth/login", user)
    }).then(function successHandler(response) {
        $window.location.href = "/";
    // if there are errors, rewrite the error messages
    }).catch(function rejectHandler(errorResponse) {
         for (prop in errorResponse.data) {
             if (prop == "email") {
                 errorResponse.data[prop] = "Please enter a valid email address.";
             } else if (prop == "username") {
                 errorResponse.data[prop] = "Please enter a valid username";
             }
         }
         //vvvv THROW to chain rejections
         throw errorResponse;
    });
}

Also it is important to use a throw statement in rejection handlers. Otherwise the rejection will be converted to a success. If a rejection handler omits a throw statement, it returns a primitive value of undefined. This means the rejection will be converted to a successful promise that resolves to a value of undefined. It will subsequently skip the .catch method in the controller.

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




回答2:


It seems like you don't have a solid understand of promises :) I recommend learning more about them.

When you call BaseService.add.user, this should return a promise. You can only use .catch if this is a promise. Also note that when chaining promises, you need to return a promise!

So something like this:

self.add = {
  user: function(user) {
    return $http.post("/users/", user)
      .then(function(response) {
        return $http.post("/api-auth/login", user)
      })
      .then(function(response) {
        $window.location.href = "/";
      })
      .catch(function(response) {
        // error stuff
      });
  }
};



回答3:


The .then() block accepts two functions for:

  1. handling a successful response
  2. handling errors

You don't need a catch block. Just add the callback function in case of errors to override the response like this:

self.add = {
            user: function(user) {
                $http.post("/users/", user)
                .then(function(response) {
                    $http.post("/api-auth/login", user)
                    .then(function(response) {
                        $window.location.href = "/";
                    }, function errorCallback(response) {
                        for (prop in response.data) {
                         if (prop == "email") {
                             response.data[prop] = "Please enter a valid email address.";
                         } else if (prop == "username") {
                             response.data[prop] = "Please enter a valid username";
                 });                    
            }
         };


来源:https://stackoverflow.com/questions/43130404/how-to-correctly-override-errresponse-which-is-passed-to-the-catchfunctione

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!