我正在使用jQuery Deferred的独立实现(git repo)。保持问题简单,如果我在任何函数中创建var status = _.Deferred()
并返回status.promise()
,那么我是否必须为该函数中的所有步骤添加try catch以reject
延迟错误?
答案 0 :(得分:3)
在返回promise之前,将在返回promise的函数内抛出,因此,no:
function foo() {
var status = _.Deferred();
throw 'DOH!';
return status.promise(); // this will never execute
}
遇到麻烦的地方是,如果在promise-returning函数中启动的异步调用可以抛出:
function bar() {
throw 'DOH!';
}
function foo() {
var status = _.Deferred();
setTimeout(function () {
status.resolve(bar());
}, 0);
return status.promise();
}
foo().
fail(function () {
// *not* invoked when bar throws
});
在这种情况下,您需要将调用包装到bar
:
function bar() {
throw 'DOH!';
}
function foo() {
var status = _.Deferred();
setTimeout(function () {
try {
status.resolve(bar());
} catch (e) {
status.reject(e);
}
}, 0);
return status.promise();
}
foo().
fail(function () {
// invoked when bar throws
});
但是,接受回调的异步函数应捕获自己的错误,并将结果或错误传递给回调。
如果异步函数改为返回promises,则不需要捕获,实际上不需要创建自己的Deferred
:
function bar() {
var d = _.Deferred();
setTimeout(function () {
d.resolve(42);
}, 0);
return d.promise();
}
function foo() {
return bar().
then(function (result) {
return result * 2;
}).
then(function (result) {
if (result === 84) { // true
throw 'DOH!';
}
));
}
foo().
then(function (result) {
// *not* invoked
}).
fail(function (e) {
console.log(e.message); // 'DOH!'
});
答案 1 :(得分:1)
在javascript中,try / catch不是像Java那样的生活方式。原因是javascript在避免可预测类型的错误方面相当丰富。
拒绝延期并非绝对必要。通常,如果您需要执行一些fail
代码,或者如果您需要积极阻止某些后续事件解决延迟,您将会这样做。
很有可能认为未解决/未被拒绝的Deferreds永远都会挂起。情况不一定如此。延迟变为可用于垃圾收集,在任何范围内都不存在对其的引用,无论是直接还是通过其承诺。
也很容易认为已解决/拒绝的Deferreds会自动被垃圾收集。这也是不真实的。如果对Deferred的引用仍然存在,在任何范围内,那么它仍然会存在于内存中,并且鉴于可以稍后调用观察者方法(例如,完成/失败/始终/然后)(并且可能立即触发),它仍然可以是有用的)。
简而言之,就GC而言,Deferreds就像任何其他js对象一样,尽管通常使用它们的代码结构使得很难发现它们何时可用于GC。