Add empty-subcription detection to frptools
bump to v1.1.0
This commit is contained in:
parent
ead1c5766a
commit
3563ee6fcb
@ -40,10 +40,12 @@ inViewport(false);
|
||||
### Subscribe to changes
|
||||
|
||||
Call the `subscribe` method with a callback that will be called when the observable is changed to a
|
||||
different value. The returned function can be called to unsubscribe from the observable.
|
||||
different value. The returned function can be called to unsubscribe from the observable. When called
|
||||
it will provide the count of remaining subscriptions.
|
||||
|
||||
```js
|
||||
const unsubscribe = inViewport.subscribe(console.log.bind(console));
|
||||
const remainingSubscriptionCount = unsubscribe();
|
||||
```
|
||||
|
||||
# [computed](./src/computed.js)
|
||||
@ -81,10 +83,12 @@ Call it to receive the stored value, recomputing if necessary.
|
||||
### Subscribe to changes
|
||||
|
||||
Call the subscribe method with a callback that will be called when the computed result changes to a
|
||||
different value. The returned function can be called to unsubscribe from the observable.
|
||||
different value. The returned function can be called to unsubscribe from the observable. When called
|
||||
it will provide the count of remaining subscriptions.
|
||||
|
||||
```js
|
||||
const unsubscribe = inViewport.subscribe(console.log.bind(console));
|
||||
const remainingSubscriptionCount = unsubscribe();
|
||||
```
|
||||
|
||||
**NOTE**: Subscribing to a computed forces it to recompute every time an upstream dependency
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "frptools",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"description": "Observable and Computed data streams",
|
||||
"main": "lib/index.js",
|
||||
"jsnext:main": "src/index.js",
|
||||
|
||||
@ -40,17 +40,107 @@ describe('computed', () => {
|
||||
|
||||
a(1);
|
||||
expect(runCount).toEqual(0);
|
||||
// b evaluates
|
||||
expect(b()).toEqual(1);
|
||||
expect(runCount).toEqual(1);
|
||||
// b does not evaluate
|
||||
expect(b()).toEqual(1);
|
||||
expect(runCount).toEqual(1);
|
||||
currentValue = 3;
|
||||
// b does not evaluate
|
||||
a(3);
|
||||
expect(runCount).toEqual(1);
|
||||
// b evaluates
|
||||
expect(b()).toEqual(9);
|
||||
expect(runCount).toEqual(2);
|
||||
});
|
||||
|
||||
it('computes automatically when subscribed', () => {
|
||||
let runCount = 0;
|
||||
let subRunCount = 0;
|
||||
let currentValue = 1;
|
||||
const a = observable(0);
|
||||
const b = computed(
|
||||
val => {
|
||||
runCount += 1;
|
||||
expect(val).toEqual(currentValue);
|
||||
return val * val;
|
||||
},
|
||||
[a]
|
||||
);
|
||||
|
||||
// b does not evaluate
|
||||
a(1);
|
||||
expect(runCount).toEqual(0);
|
||||
// b evaluates
|
||||
expect(b()).toEqual(1);
|
||||
expect(runCount).toEqual(1);
|
||||
// b does not evaluate
|
||||
expect(b()).toEqual(1);
|
||||
expect(runCount).toEqual(1);
|
||||
|
||||
const cancelSubscription = b.subscribe(val => {
|
||||
subRunCount += 1;
|
||||
expect(val).toEqual(currentValue * currentValue);
|
||||
});
|
||||
|
||||
currentValue = 3;
|
||||
// b evaluates
|
||||
a(3);
|
||||
expect(runCount).toEqual(2);
|
||||
expect(subRunCount).toEqual(1);
|
||||
// b does not evaluate
|
||||
expect(b()).toEqual(9);
|
||||
expect(runCount).toEqual(2);
|
||||
expect(subRunCount).toEqual(1);
|
||||
});
|
||||
|
||||
it('honors cancelled subscriptions', () => {
|
||||
let runCount = 0;
|
||||
let subRunCount = 0;
|
||||
let currentValue = 1;
|
||||
const a = observable(0);
|
||||
const b = computed(
|
||||
val => {
|
||||
runCount += 1;
|
||||
expect(val).toEqual(currentValue);
|
||||
return val * val;
|
||||
},
|
||||
[a]
|
||||
);
|
||||
const cancelSubscription = b.subscribe(val => {
|
||||
subRunCount += 1;
|
||||
expect(val).toEqual(currentValue * currentValue);
|
||||
});
|
||||
|
||||
const cancelSubscription2 = b.subscribe(val => {
|
||||
subRunCount += 1;
|
||||
});
|
||||
|
||||
// b evaluates
|
||||
a(1);
|
||||
expect(runCount).toEqual(1);
|
||||
expect(subRunCount).toEqual(2);
|
||||
// b does not evaluate
|
||||
expect(b()).toEqual(1);
|
||||
expect(runCount).toEqual(1);
|
||||
expect(subRunCount).toEqual(2);
|
||||
|
||||
expect(cancelSubscription()).toEqual(1);
|
||||
|
||||
currentValue = 3;
|
||||
// b evaluates
|
||||
a(3);
|
||||
expect(runCount).toEqual(2);
|
||||
expect(subRunCount).toEqual(3);
|
||||
// b does not evaluate
|
||||
expect(b()).toEqual(9);
|
||||
expect(runCount).toEqual(2);
|
||||
expect(subRunCount).toEqual(3);
|
||||
|
||||
expect(cancelSubscription2()).toEqual(0);
|
||||
});
|
||||
|
||||
it('can be detached', () => {
|
||||
const a = observable(2);
|
||||
const b = computed(square, [a]);
|
||||
|
||||
@ -44,12 +44,21 @@ describe('observable', () => {
|
||||
runCount += 1;
|
||||
expect(val).toEqual(currentValue);
|
||||
});
|
||||
const cancelSubscription2 = a.subscribe(val => {
|
||||
runCount += 1;
|
||||
expect(val).toEqual(currentValue);
|
||||
});
|
||||
expect(a(1)).toEqual(1);
|
||||
expect(runCount).toEqual(1);
|
||||
expect(runCount).toEqual(2);
|
||||
expect(a(1)).toEqual(1);
|
||||
expect(runCount).toEqual(1);
|
||||
cancelSubscription();
|
||||
expect(runCount).toEqual(2);
|
||||
expect(cancelSubscription()).toEqual(1);
|
||||
currentValue = 3;
|
||||
expect(a(3)).toEqual(3);
|
||||
expect(runCount).toEqual(1);
|
||||
expect(runCount).toEqual(3);
|
||||
expect(cancelSubscription2()).toEqual(0);
|
||||
currentValue = 4;
|
||||
expect(a(4)).toEqual(4);
|
||||
expect(runCount).toEqual(3);
|
||||
});
|
||||
});
|
||||
|
||||
@ -31,7 +31,10 @@ export function computed(fn, dependencies = []) {
|
||||
|
||||
accessor.subscribe = fn => {
|
||||
subscribers.add(fn);
|
||||
return () => subscribers.delete(fn);
|
||||
return () => {
|
||||
subscribers.delete(fn);
|
||||
return subscribers.size;
|
||||
};
|
||||
};
|
||||
|
||||
accessor._d = fn => {
|
||||
|
||||
@ -11,7 +11,10 @@ export function observable(store) {
|
||||
|
||||
accessor.subscribe = accessor._d = fn => {
|
||||
subscribers.add(fn);
|
||||
return () => subscribers.delete(fn);
|
||||
return () => {
|
||||
subscribers.delete(fn);
|
||||
return subscribers.size;
|
||||
};
|
||||
};
|
||||
|
||||
accessor.unsubscribeAll = () => subscribers.clear();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user