Skip to content

Commit

Permalink
If a computed evaluator throws an exception, dependencies are correct.
Browse files Browse the repository at this point in the history
  • Loading branch information
mbest committed Dec 16, 2013
1 parent d1c7470 commit fc5b89a
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 20 deletions.
28 changes: 17 additions & 11 deletions spec/dependentObservableBehaviors.js
Original file line number Diff line number Diff line change
Expand Up @@ -406,29 +406,35 @@ describe('Dependent Observable', function() {
});

it('Should be able to re-evaluate a computed that previously threw an exception', function() {
var observable = ko.observable(true),
var observableSwitch = ko.observable(true), observableValue = ko.observable(1),
computed = ko.computed(function() {
if (!observable()) {
throw Error("Some dummy error");
if (!observableSwitch()) {
throw Error("Error during computed evaluation");
} else {
return observable();
return observableValue();
}
});

// Initially the computed value is true (executed sucessfully -> same value as observable)
expect(computed()).toEqual(true);
// Initially the computed evaluated sucessfully
expect(computed()).toEqual(1);

expect(function () {
// Update observable to cause computed to throw an exception
observable(false);
}).toThrow();
observableSwitch(false);
}).toThrow("Error during computed evaluation");

// The value of the computed is now undefined, although currently it keeps the previous value
expect(computed()).toEqual(true);
expect(computed()).toEqual(1);
// The computed should not be dependent on the second observable
expect(computed.getDependenciesCount()).toEqual(1);

// Update observable to cause computed to re-evaluate
observable(1);
// Updating the second observable shouldn't re-evaluate computed
observableValue(2);
expect(computed()).toEqual(1);

// Update the first observable to cause computed to re-evaluate
observableSwitch(1);
expect(computed()).toEqual(2);
});

it('Should expose a "notify" extender that can configure a computed to notify on all changes', function() {
Expand Down
22 changes: 13 additions & 9 deletions src/subscribables/dependentObservable.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,21 @@ ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunction
_subscriptionsToDependencies = {};
_dependenciesCount = 0;

var newValue = evaluatorFunctionTarget ? readFunction.call(evaluatorFunctionTarget) : readFunction();
try {
var newValue = evaluatorFunctionTarget ? readFunction.call(evaluatorFunctionTarget) : readFunction();

// For each subscription no longer being used, remove it from the active subscriptions list and dispose it
if (disposalCount) {
ko.utils.objectForEach(disposalCandidates, function(id, toDispose) {
toDispose.dispose();
});
}
} finally {
ko.dependencyDetection.end();

// For each subscription no longer being used, remove it from the active subscriptions list and dispose it
if (disposalCount) {
ko.utils.objectForEach(disposalCandidates, function(id, toDispose) {
toDispose.dispose();
});
}

_hasBeenEvaluated = true;
_hasBeenEvaluated = true;
}

if (!dependentObservable['equalityComparer'] || !dependentObservable['equalityComparer'](_latestValue, newValue)) {
dependentObservable["notifySubscribers"](_latestValue, "beforeChange");
Expand All @@ -105,7 +110,6 @@ ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunction
dependentObservable["notifySubscribers"](_latestValue);
}
} finally {
ko.dependencyDetection.end();
_isBeingEvaluated = false;
}

Expand Down

0 comments on commit fc5b89a

Please sign in to comment.