Angular $q catch 块已解决承诺?
Angular $q catch block resolves promis?
在过去的几天里,我阅读了很多处理 promises 的最佳实践。大多数帖子的一个中心点是这样的:
So if you are writing that word [deferred] in your code
[...], you are doing something wrong.1
在尝试错误处理期间,我看到了一个对我来说意想不到的行为。当我将 promise 和 It 运行 链接到第一个 catch 块时,第二个 promise 得到解决并且没有被拒绝。
问题
- 这是否也是其他库/标准(例如 q、es6)中的正常行为,并且捕获的错误算作已解决,就像在 try / catch 中一样?
- 如何拒绝 catch 块中的 promise,以便第二个被调用并使用 相同的错误/响应 对象?
例子
在此示例中,您会看到 'I am here but It was an error'
function BaseService($http, $q) {
this.$http = $http;
this.$q = $q;
}
BaseService.prototype.doRequest = function doRequest() {
return this.$http({
method: 'GET',
url: 'not/exisint/url'
})
.then(function (response) {
// do some basic stuff
})
.catch(function(response) {
// do some baisc stuff e.g. hide spinner
});
}
function ChildService($http, $q) {
this.$http = $http;
this.$q = $q;
}
ChildService.prototype = Object.create(BaseService.prototype);
ChildService.prototype.specialRequest = function specialRequest() {
return this.doRequest()
.then(function (response) {
alert('I am here but It was an error');
})
.catch(function (response) {
// do some more specific stuff here and
// provide e.g. error message
alert('I am here but It was an error');
return response;
});
}
解决方法:
使用此解决方法可以解决此问题,但您必须创建一个新的延迟。
BaseService.prototype.doRequest = function doRequest() {
var dfd = this.$q.defer();
return this.$http({
method: 'GET',
url: 'not/exisint/url'
})
.then(function (response) {
// do some basic stuff
dfd.resolve(response);
})
.catch(function(response) {
// do some basic stuff e.g. hide spinner
dfd.reject(error);
});
}
您的解决方法几乎是正确的,您可以将其简化为以下内容:
BaseService.prototype.doRequest = function doRequest() {
return this.$http({
method: 'GET',
url: 'not/exisint/url'
})
.then(function (response) {
// do some basic stuff
return response;
}, function (error) {
return this.$q.reject(error);
});
}
$q.reject
是创建立即被拒绝的延迟的快捷方式。
- 是的,这也是其他库中的默认行为。
.then
或 .catch
只是将 return 值包装到一个新的承诺中。您可以 return 拒绝承诺以使 .catch
链工作。
你也可以反其道而行之,例如当你出于任何原因想要拒绝成功回调中的承诺时:
function getData() {
return this.$http.get(endpoint).then(result => {
// when result is invalid for whatever reason
if (result === invalid) {
return this.$q.reject(result);
}
return result;
}, err => this.$q.reject(err));
}
getData().then(result => {
// skipped
}, error => {
// called
});
- 见上例
只是为了添加到 答案和解决方法中,您还可以将代码包装到 $q 构造函数中:
BaseService.prototype.doRequest = function doRequest() {
return $q(function (resolve, reject) {
$http.get('not/exisint/url').then(function (response) { // success
/* do stuff */
resolve(response);
}, function (error) { // failure
/* do stuff */
reject(error);
});
});
};
在过去的几天里,我阅读了很多处理 promises 的最佳实践。大多数帖子的一个中心点是这样的:
So if you are writing that word [deferred] in your code [...], you are doing something wrong.1
在尝试错误处理期间,我看到了一个对我来说意想不到的行为。当我将 promise 和 It 运行 链接到第一个 catch 块时,第二个 promise 得到解决并且没有被拒绝。
问题
- 这是否也是其他库/标准(例如 q、es6)中的正常行为,并且捕获的错误算作已解决,就像在 try / catch 中一样?
- 如何拒绝 catch 块中的 promise,以便第二个被调用并使用 相同的错误/响应 对象?
例子
在此示例中,您会看到 'I am here but It was an error'
function BaseService($http, $q) {
this.$http = $http;
this.$q = $q;
}
BaseService.prototype.doRequest = function doRequest() {
return this.$http({
method: 'GET',
url: 'not/exisint/url'
})
.then(function (response) {
// do some basic stuff
})
.catch(function(response) {
// do some baisc stuff e.g. hide spinner
});
}
function ChildService($http, $q) {
this.$http = $http;
this.$q = $q;
}
ChildService.prototype = Object.create(BaseService.prototype);
ChildService.prototype.specialRequest = function specialRequest() {
return this.doRequest()
.then(function (response) {
alert('I am here but It was an error');
})
.catch(function (response) {
// do some more specific stuff here and
// provide e.g. error message
alert('I am here but It was an error');
return response;
});
}
解决方法:
使用此解决方法可以解决此问题,但您必须创建一个新的延迟。
BaseService.prototype.doRequest = function doRequest() {
var dfd = this.$q.defer();
return this.$http({
method: 'GET',
url: 'not/exisint/url'
})
.then(function (response) {
// do some basic stuff
dfd.resolve(response);
})
.catch(function(response) {
// do some basic stuff e.g. hide spinner
dfd.reject(error);
});
}
您的解决方法几乎是正确的,您可以将其简化为以下内容:
BaseService.prototype.doRequest = function doRequest() {
return this.$http({
method: 'GET',
url: 'not/exisint/url'
})
.then(function (response) {
// do some basic stuff
return response;
}, function (error) {
return this.$q.reject(error);
});
}
$q.reject
是创建立即被拒绝的延迟的快捷方式。
- 是的,这也是其他库中的默认行为。
.then
或.catch
只是将 return 值包装到一个新的承诺中。您可以 return 拒绝承诺以使.catch
链工作。
你也可以反其道而行之,例如当你出于任何原因想要拒绝成功回调中的承诺时:
function getData() {
return this.$http.get(endpoint).then(result => {
// when result is invalid for whatever reason
if (result === invalid) {
return this.$q.reject(result);
}
return result;
}, err => this.$q.reject(err));
}
getData().then(result => {
// skipped
}, error => {
// called
});
- 见上例
只是为了添加到
BaseService.prototype.doRequest = function doRequest() {
return $q(function (resolve, reject) {
$http.get('not/exisint/url').then(function (response) { // success
/* do stuff */
resolve(response);
}, function (error) { // failure
/* do stuff */
reject(error);
});
});
};