There’s another way to invoke a writer: the write method.
source.write takes in two arguments. The first is the writer’s name and the second is the argument you want to pass to the writer.

Hence, addTodo above could be rewritten as

...addTodo(text){
source.write('addTodo', text)
}
...

Both methods provide the same functionality. Using write, however, limits you to one argument. The latter method may look a bit more familiar if you’re coming from flux/redux.

Runners

Writers have one catch: they update your components synchronously. This means asynchronous changes ( made via API calls, WebSockets, or setTimeouts, etc. ) may not have updated truth by the time Ethos updates your components.

To solve this problem, we have runners. Ethos runners handle all asynchronous activity in the source. Put simply, runnersrun other functions.

You may have noticed we already have a time property in the truth of our example. Let’s make it update once per second.

Now when getRandomGifUrl runs, it will return a Promise. The following will be possible:

let defaultImageUrl ='https://media.giphy.com/media/UbQs9noXwuSFa/giphy.gif?response_id=591ccaaaecadb1fa9e03044c'source.runners.getRandomGifUrl()
.then((imageUrl)=>{
/* imagine you have a function which changes the source of an image*/setImageSrc(imageUrl)
})
.catch((error)=>{
setImageSrc(defaultImageUrl)
})

In many cases, using async and await is the optimal path, but Promise wrappers are nice for when your asynchronous code doesn’t already utilize promises.

Watchers

A watcher is a function that is invoked whenever a property on truth changes.
Watchers are defined like so:

Thoughts

Thoughts observe one or more pieces of truth, combine it with some custom logic, and return a new piece of truth. When a piece of truth a thought is observing changes, the thought will update its value.
Let’s say we have two numbers, a and b, in our truth.

Founder Function

In an Ethos Source, the founder function is a function that is instantly invoked once the store is built. It can be used to initialize a lot of store functionality an avoid contaminating your view layer with store logic.