问题
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 sayingTypeError: 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:
- handling a successful response
- 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