Skip to content

Commit

Permalink
feat(watch): watch setters on an object
Browse files Browse the repository at this point in the history
  • Loading branch information
MrAntix committed Aug 5, 2019
1 parent 71aa6e9 commit 7a6b15d
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/IWatchHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface IWatchHandler {
(value?: any): void;
}
64 changes: 64 additions & 0 deletions src/watch.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { watch } from './watch';

describe('watch', () => {
const prop = 'PROPERTY';
const value = 'VALUE';
let o;

beforeEach(() => {
o = {};
});

it('watches for change', () => {
let counter = 0;
watch(o, prop, () => {
counter++;
});

o[prop] = value;
o[prop] = value;

expect(counter).toBe(2);
});

it('watches for change once', () => {
let counter = 0;
watch(
o,
prop,
() => {
counter++;
},
true
);

o[prop] = value;
o[prop] = value;

expect(counter).toBe(1);
});

it('unwatches and keeps set value', () => {
const unwatch = watch(o, prop, () => {});

o[prop] = value;
unwatch();

expect(o[prop]).toBe(value);
});

it('can nest watches', () => {
let counter = 0;
watch(o, prop, () => {
counter++;
});
watch(o, prop, () => {
counter++;
});

o[prop] = value;
o[prop] = value;

expect(counter).toBe(4);
});
});
38 changes: 38 additions & 0 deletions src/watch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { IWatchHandler } from './IWatchHandler';

export function watch(
o: any,
property: string,
handler: IWatchHandler,
once = false
): () => void {

const descriptor = Object.getOwnPropertyDescriptor(o, property) || {};

let getValue = descriptor.get || (() => descriptor.value);
let setValue = descriptor.set || (value => (descriptor.value = value));

const unwatch = () => {
delete o[property];
o[property] = getValue();
};

Object.defineProperty(o, property, {
get: getValue,
set(value) {
if (once && getValue() === undefined) {
setValue(value);
unwatch();
handler(value);

return;
}

setValue(value);
handler(value);
},
configurable: true
});

return unwatch;
}

0 comments on commit 7a6b15d

Please sign in to comment.