Skip to content

Instantly share code, notes, and snippets.

@far-blue
Created July 2, 2017 22:35
Show Gist options
  • Save far-blue/bf1e280e5218413c11e60e32bf9fd94b to your computer and use it in GitHub Desktop.
Save far-blue/bf1e280e5218413c11e60e32bf9fd94b to your computer and use it in GitHub Desktop.
Example extension of Type-R to support TC39 draft Observable interface specifically for change events and streaming only the changed properties.
<html>
<head>
<title></title>
</head>
<body>
<script src="most.js"></script>
<script src="type-r.js"></script>
<script>
// Support environments without Symbol support.
// ---------
// return an existing named symbol, a new named symbol or the compat '@@observable' string.
Nested.symbolCompat = function() {
return (typeof Symbol === 'function' ? (Symbol.observable ? Symbol.observable : Symbol('observable')) : '@@observable');
};
// Requirements for being Observable
// --------
// Named symbol for observable. Holds a function that returns a subscription object.
Nested.Record.prototype[Nested.symbolCompat()] = function() {
return { subscribe: this.subscription.bind(this) };
};
// Create a subscription and return a function that can dispose of the subscription
Nested.Record.prototype.subscription = function (thingObserving) {
let f = (model) => thingObserving.next(model.changedAttributes());
this.on('change', f);
return function() { this.off('change', f); };
};
// Requirements for being an Observer
// --------
// To be an Observer, a next() function is required.
Nested.Record.prototype.next = function (newValues) { this.set(newValues); };
// Example usage:
// Create 2 user instances, Observe the first.
// Set the second user to Observe the stream of property changes.
// console log in various places to show the workings.
// --------
var ExampleUser = Nested.Record.extend({
attributes: {
username: ''
}
});
let user1 = new ExampleUser();
let user2 = new ExampleUser();
let user1Observable = most.from(user1);
let user2Observable = most.from(user2);
// Log all events in the stream from user1
user1Observable.observe((value) => console.log('user1', value));
let mappedUser1 = user1Observable
.map(function (e) {
let result = Object.assign({}, e);
for (let prop in result) {
result[prop] += 'Yeah!';
}
return result;
});
// log the stream of remapped key/value pairs
mappedUser1.observe((value) => console.log('mapped user1', value));
// Subscribe to the change stream with user2
// so user2's properties are updated
mappedUser1.subscribe(user2);
// Actually change the username property on user1 to see the
// chains of streams in action
user1.username = 'greenback';
user1.username = 'penfold';
// Show the resulting content of the 2 records.
console.log(user1, user2);
</script>
</body>
</html>
@far-blue
Copy link
Author

far-blue commented Jul 2, 2017

Compared to https://gist.github.com/far-blue/05c679b4e4cb5fe1df1d36006e8a21fa, this gist only observes change events and pushes only details of the changed attributes rather than a full event object. This makes the stream specific to Records rather than working for any event but makes the use of the stream much easier and creates a 'mirror' between the observe and consume where no transformations are needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment