- message: any value (string, obj, etc)
- channel: uni-directional paths that messages travel across
- multichannel: you can wrap multiple channels in a single channel by wrapping the message with metadata
message = {
channel: 'channelA',
data: originalMessage,
}
- duplex channel: you can have bi-directional communication by pairing 2 uni-directional channels in opposite directions
-
pull:
- send request, get response
- calling a fn
- lazy-computed values
- pull-streams
- sending eth rpc requests
-
push:
- send data
- handler being called
- event emitters
- observables (redux store)
- current block (via poller)
- standard streams
- receiving dapp eth rpc requests
- push->pull (cache/disk)
- pull->push (poll/network)
both
- transform
push
- filter
- debounce
- throttle
- mux/demux
- waitForValuesPopulated
pull
- cache
- obervable obj (observ)
- state transition process (simple set, reducer)
- semantic api (wrapper / dnode)
same behavior remote+local ( async set's ) same API for observing ( despite reducer or obervable )
recompute strategies:
- lazy (pull only except for 'wait for first handlers' optimization)
- eager
flow API:
- streams
- handlers
channels:
- single (simpler API)
- multiple (more control over granularity/type of update)
locality:
- local
- remote (can we stream in a remote store with the same API?)
pubsub. multiple channels.
ee.on('a', fn)
ee.on('b', fn)
ee.emit('a', data)
observable store. processes state transitions via reducers. emits new result immediately.
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
// Create a Redux store holding the state of your app.
// Its API is { subscribe, dispatch, getState }.
let store = createStore(counter)
// You can use subscribe() to update the UI in response to state changes.
// Normally you’d use a view binding library (e.g. React Redux) rather than subscribe() directly.
// However it can also be handy to persist the current state in the localStorage.
store.subscribe(() =>
console.log(store.getState())
)
// The only way to mutate the internal state is to dispatch an action.
// The actions can be serialized, logged or stored and later replayed.
store.dispatch({ type: 'INCREMENT' })
observable store. single channel. calls new listener immediately.
allows simple usage of set
.
// create + set initial
var v = Observable("initial value")
// listen
var stopListening = v(function onchange(newValue) {
assert.equal(newValue, "new value")
})
// set
v.set("new value")
compose observables
var one = Observable(1)
var two = Observable(2)
var together = computed([one, two], function (a, b) {
return a + b
})
children are also obserables
var state = ObservStruct({
fruits: ObservStruct({
apples: Observ(3),
oranges: Observ(5)
}),
customers: Observ(5)
})
state(function (current) {
console.log("apples", current.fruits.apples)
console.log("customers", current.customers)
})
state.fruits(function (current) {
console.log("apples", current.apples)
})
var initialState = state()
assert.equal(initialState.fruits.oranges, 5)
assert.equal(initialState.customers, 5)
state.fruits.oranges.set(6)
state.customers.set(5)
state.fruits.apples.set(4)
magical overkill. name re-compute dependencies with a string. some fancy stuff for pattern matching properties against children of Arrays.
Ember.Object.extend({
valueObserver: Ember.observer('value', function(sender, key, value, rev) {
// Executes whenever the "value" property changes
// See the addObserver method for more information about the callback arguments
})
});
streams that pull data instead of push, allowing lazy evaluation.
pull(
pull.values(['file1', 'file2', 'file3']),
pull.asyncMap(fs.stat),
pull.collect(function (err, array) {
console.log(array)
})
)
stream-like flow control lib
/* Get stock data somehow */
const source = getAsyncStockData();
const subscription = source
.filter(quote => quote.price > 30)
.map(quote => quote.price)
.subscribe(
price => console.log(`Prices higher than $30: ${price}`),
err => console.log(`Something went wrong: ${err.message}`);
);
/* When we're done */
subscription.dispose();
EthStore Pull->Push Adapter
http://www.nomnoml.com/#view/%0A%5BEthStore%20Pull-%3EPush%20Adapter%7C%0A%20%20%5B%3Cstate%3Epull%20rpc%20in%5D%0A%20%20%5B%3Cstate%3Epush%20state%20out%5D%0A%20%20%5Bblock%20poller%5D-%3E%5Bpull%20rpc%20in%5D%0A%20%20%5Beth-store%5D%3C%3A-%5Bblock%20poller%5D%0A%20%20%5Bsubs%5D-%3A%3E%5Beth-store%5D%0A%20%20%5Beth-store%5D-%3E%5Bpull%20rpc%20in%5D%0A%20%20%5Beth-store%5D-%3A%3E%5Bpush%20state%20out%5D%0A%5D%0A
With account view rendering
http://www.nomnoml.com/#view/%5BEthStore%20Pull-%3EPush%20Adapter%7C%0A%20%20%5B%3Cstate%3Epull%20rpc%20in%5D%0A%20%20%5B%3Cstate%3Epush%20state%20out%5D%0A%20%20%5Bblock%20poller%5D-%3E%5Bpull%20rpc%20in%5D%0A%20%20%5Beth-store%5D%3C%3A-%5Bblock%20poller%5D%0A%20%20%5B%3Cstate%3Esubs%5D-%3A%3E%5Beth-store%5D%0A%20%20%5Beth-store%5D-%3E%5Bpull%20rpc%20in%5D%0A%20%20%5Beth-store%5D-%3A%3E%5Bpush%20state%20out%5D%0A%5D%0A%0A%5Baccounts%20view%5D-%3A%3E%5Beth-store%20subs%5D%0A%5Beth-store%20subs%5D-%3A%3E%5Beth-store%5D%0A%5Beth-store%5D-%3A%3E%5Baccounts%20view%5D%0A%5Beth-store%5D-%3E%5Brpc%5D%0A%5Baccounts%20view%5D-%3A%3E%5Bdom%5D%0A%5Bdom%5D-%3A%3E%5Baction%20handler%5D%0A%5Baction%20handler%5D-%3A%3E%5Bid%20mgmt%5D%0A%0A%5Bid%20mgmt%5D-%3A%3E%5Beth-store%20subs%5D%0A%0A