Reputation: 4696
I'm using a standalone implementation (git repo) of the jQuery Deferred. Keeping the question simple, if I make a var status = _.Deferred()
and return status.promise()
from within any function, do I then have to add a try catch for all steps within that function to reject
the deferred on error?
Upvotes: 2
Views: 1555
Reputation: 6581
Throwing from within the function that returns the promise will occur before the promise is returned, so, no:
function foo() {
var status = _.Deferred();
throw 'DOH!';
return status.promise(); // this will never execute
}
Where you run into trouble is if async calls initiated in the promise-returning function can throw:
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
});
In this case, you would need to wrap the call to 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
});
However, async functions that accept a callback should catch their own errors, and pass the result or error to the callback.
If the async functions instead return promises, you do not need to catch and in fact do not need to create your own 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!'
});
Upvotes: 3
Reputation: 18078
In javascript, try/catch isn't a way of life as in say Java. The reason is that javascript is fairly rich in ways to avoid predictable types of error.
It's not strictly necessary to reject a Deferred. Typically you will do so if you need to execute some fail
code, or if you need to positively prevent some later event resolving the Deferred.
It is tempting to think that unresolved/unrejected Deferreds hang for ever. This is not necessarily the case. A Deferred becomes available for garbage collection at such time that no reference to it exists in any scope, either directly or via its promise.
It is also tempting to think that resolved/rejected Deferreds are automatically garbage collected. This is also untrue. If a reference to a Deferred still exists, in any scope, then it will still be present in memory, and can still be useful given that watcher methods (eg done/fail/always/then) may be invoked later (and may fire immediately).
In short, with regard to GC, Deferreds are just like any other js object, though the code structures in which they are typically used make it difficult to spot when they might become available for GC.
Upvotes: 1