Skip to content
Browse files

Add lazy computables.

  • Loading branch information...
1 parent 87ce0f9 commit 51ac83a75321d5e89dedfbf043aee1bdc53a34ec @Osmose committed May 12, 2012
Showing with 56 additions and 11 deletions.
  1. +11 −0 README.md
  2. +24 −11 observe.js
  3. +21 −0 tests/tests.js
View
11 README.md
@@ -73,6 +73,17 @@ function Person(first_name, last_name) {
}, this);
}
new Person('Michael', 'Kelly').full_name(); // = 'Michael Kelly'
+
+// Create a lazy computed variable. Does not update when dependencies change,
+// only when read.
+var dependency = observable(1);
+var myvar = computed(function() {
+ return dependency() + 1;
+});
+myvar.lazy = true;
+
+dependency(2);
+myvar(); // myvar isn't reevaluated until this line.
```
## Misc
View
35 observe.js
@@ -44,6 +44,7 @@
* If write is not provided, variable is read-only.
*/
ob.computed = function(read, write, context) {
+ var changed = false;
var listeners = [];
// Swap write and context if write is not a function.
@@ -52,24 +53,19 @@
write = undefined;
}
- // Track dependencies.
- global_dependencies = [];
- var _value = read.call(context);
- for (var k = 0; k < global_dependencies.length; k++) {
- global_dependencies[k].onchange(function() {
- _value = read.call(context);
- notifyListeners(listeners, _value);
- });
- }
- global_dependencies = null;
-
var computed = function() {
if (arguments.length === 0) {
// Add to global dependencies if being tracked.
if (global_dependencies !== null) {
global_dependencies.push(computed);
}
+ // Check for lazy evaluation.
+ if (computed.lazy === true && changed === true) {
+ _value = read.call(context);
+ notifyListeners(listeners, _value);
+ }
+
return _value;
} else if (write === undefined) {
// TODO: Better error message.
@@ -83,8 +79,25 @@
}
};
+ computed.lazy = false; // If true, does not evaluate the new value
+ // after a dependency changes until this is read.
computed.onchange = createOnChange(listeners);
+ // Track dependencies.
+ global_dependencies = [];
+ var _value = read.call(context);
+ for (var k = 0; k < global_dependencies.length; k++) {
+ global_dependencies[k].onchange(function() {
+ if (computed.lazy === true) {
+ changed = true;
+ } else {
+ _value = read.call(context);
+ notifyListeners(listeners, _value);
+ }
+ });
+ }
+ global_dependencies = null;
+
return computed;
};
View
21 tests/tests.js
@@ -136,4 +136,25 @@ define(function(require) {
myvar(2);
equal(myvar3(), 'myvar2 is 3');
});
+
+ test('Computed variables can be set to evaluate only when read.',
+ function() {
+ var called = 0;
+
+ var dependency = observable(1);
+ var myvar = computed(function() {
+ called++;
+ return dependency() + 1;
+ });
+ equal(called, 1);
+
+ dependency(2);
+ equal(called, 2);
+
+ myvar.lazy = true;
+ dependency(3);
+ equal(called, 2);
+ myvar();
+ equal(called, 3);
+ });
});

0 comments on commit 51ac83a

Please sign in to comment.
Something went wrong with that request. Please try again.