Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Import it using:
import { Reactor, Observer, hide, batch, shuck } from 'reactorjs'
```

It is also available directly from [unpkg](unpkg.com). You can import it in JavaScript using:
It is also available directly from [unpkg](https://unpkg.com). You can import it in JavaScript using:
```javascript
import { Reactor, Observer, hide, batch, shuck } from 'https://unpkg.com/reactorjs'
```
Expand Down Expand Up @@ -266,6 +266,7 @@ observer() // prints "hola"
Like normal functions, observers can expect and be called with arguments. They remember the arguments from the last time they were called and reuse them when automatically triggered:

```javascript
const reactor = new Reactor({ foo: 'baz' })
const parameterizedObserver = new Observer((arg1, arg2) => {
console.log(reactor.foo + arg1 + arg2)
})
Expand All @@ -276,6 +277,7 @@ reactor.foo = 'bla' // prints blabeepbop
Observers can also use and remember the last `this` context. Note that just like normal functions, for the `this` context to be bound to the holding object, it needs to be defined with the traditional `function` keyword instead of ES6 arrow functions:

```javascript
const reactor = new Reactor({ foo: 'bla' })
const holdingObject = {
name: 'Mario',
greet: new Observer(function () { // Need to use `function`
Expand Down Expand Up @@ -379,7 +381,7 @@ batch(() => {

This is useful when you are making multiple data updates and want to avoid showing an "incomplete" view of the data to observers.

Note that only the observer triggering is postponed until the end. The actual reactor properties are updated in place as expected. This means that you can have other logic with read-what-you-write semantics within the observer block working just fine.
Note that only the observer triggering is postponed until the end. The actual reactor properties are updated in place as expected. This means that you can have other logic with read-what-you-write semantics within the batch block working just fine.

Summary
-------
Expand All @@ -398,24 +400,24 @@ reactor.foo = 'baz' // prints 'reactor.foo is baz'
observer.stop()
reactor.foo = 'qux' // prints nothing since observer is stopped

observer.start() // prints 'reactor.foo is baz'
observer.start() // prints 'reactor.foo is qux'
observer.start() // prints nothing since observer is already started
observer() // prints 'reactor.foo is baz' even if it is already running
observer() // prints 'reactor.foo is qux' even if it is already running

// Observer return values are themselves observable
const trailingObserver = new Observer(() => {
const result = 'Did you hear: ' + observer.value
console.log(result)
})
trailingObserver() // prints 'Did you hear: reactor.foo is baz'
trailingObserver() // prints 'Did you hear: reactor.foo is qux'
reactor.foo = 'blorp' // prints 'reactor.foo is blorp' from observer
// also prints 'Did you hear: reactor.foo is blorp' from trailingObserver

// Observers can be given parameters and remember these parameters when triggered
const parameterizedObserver = new Observer((arg1, arg2) => {
console.log(reactor.foo + arg1 + arg2)
})
parameterizedObserver('beep', 'bop') // prints bazbeepbop
parameterizedObserver('beep', 'bop') // prints blorpbeepbop
reactor.foo = 'bla' // prints blabeepbop

// Observers can also access and remember the last `this` context
Expand Down Expand Up @@ -468,7 +470,7 @@ Map.prototype.keys.call(shuck(mapReactor)) // works fine

Development & Testing
---------------------
Tests are stored in `test.js` to be run using Mocha.
Tests are stored in `test/` to be run using the Node.js built-in test runner.

Run `npm install` to install the dev dependencies.

Expand Down
10 changes: 5 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { WeakRefSet } from 'weak-ref-collections'
// - The reader gets added as a dependent of the readee
// - The readee gets added as a dependency of the reader
// - When the signal evaluation is done, the observer pops itself off the stack
// The stack is used to track the latest signal caller automaticaly
// The stack is used to track the latest active observer automatically
// Using a stack allows nested signals to function correctly
const dependencyStack = []

Expand All @@ -19,7 +19,7 @@ const reactorCoreExtractor = new WeakMap()
const observerCoreExtractor = new WeakMap()

// A batcher is used to postpone observer triggers and batch them together
// When "batch" is called it adds sets a batcher to this global variable
// When "batch" is called it sets a batcher to this global variable
// When a Signal is updated it checks if a batcher is set
// If it is, it adds that observer to this set instead of triggering it
// At the end of the execution, the batch call then calls all the observers
Expand All @@ -42,8 +42,8 @@ const reactorCache = new WeakMap()

// Helper function for checking if something is an object
function isObject (x) {
// functions are objects also but typeof to function
// nulls are not objects but typeof to objects
// functions are objects but typeof returns 'function'
// nulls are not objects but typeof returns 'object'
// the last bit is to check for nulls
const type = typeof (x)
return ((type === 'function' || type === 'object') && !!x)
Expand Down Expand Up @@ -507,7 +507,7 @@ class Reactor {
// b.foo = "bar"
// let observer = new Observer(() => { This will trigger whenever
// console.log("a is now " + a()) a or b.foo are updated
// console.log("b.foois now " + b.foo)
// console.log("b.foo is now " + b.foo)
// })
// observer()
// a(2) This will trigger an update
Expand Down