{"id":19279001,"url":"https://github.com/krasimir/riew","last_synced_at":"2025-04-22T00:32:11.001Z","repository":{"id":57159474,"uuid":"198757161","full_name":"krasimir/riew","owner":"krasimir","description":"Riew is a reactive library that uses CSP concepts for managing data and application flow.","archived":false,"fork":false,"pushed_at":"2020-03-02T10:43:03.000Z","size":19329,"stargazers_count":24,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-05T12:05:10.675Z","etag":null,"topics":["buffer","csp","javascript","pubsub","reactive","routines"],"latest_commit_sha":null,"homepage":"https://krasimirtsonev.com/blog/category/Riew","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/krasimir.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-07-25T04:27:38.000Z","updated_at":"2022-05-06T01:42:17.000Z","dependencies_parsed_at":"2022-09-07T20:12:12.003Z","dependency_job_id":null,"html_url":"https://github.com/krasimir/riew","commit_stats":null,"previous_names":["krasimir/rine"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krasimir%2Friew","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krasimir%2Friew/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krasimir%2Friew/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krasimir%2Friew/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/krasimir","download_url":"https://codeload.github.com/krasimir/riew/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223670462,"owners_count":17183320,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["buffer","csp","javascript","pubsub","reactive","routines"],"created_at":"2024-11-09T21:12:55.770Z","updated_at":"2024-11-09T21:12:56.542Z","avatar_url":"https://github.com/krasimir.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Riew logo](./assets/riew.jpg)\n![Riew what it does](./assets/what-is-riew-animation.gif)\n\n---\n\n\u003ch3 align=\"center\"\u003eReactive View\u003c/h3\u003e\n\n\u003cp align=\"center\"\u003e\u003cb\u003eRiew\u003c/b\u003e is a reactive library that uses \u003ca href=\"https://en.wikipedia.org/wiki/Communicating_sequential_processes\"\u003eCSP\u003c/a\u003e concepts for managing data and application flow.\u003c/p\u003e\n\n---\n\n**📚 Learning materials**\n\n* [Reactive view - the concept](https://krasimirtsonev.com/blog/article/riew-reactive-view-concept)\n* [Part 1: We need channels! A gentle introduction to CSP](https://krasimirtsonev.com/blog/article/we-need-channels-intro-to-csp)\n* [Part 2: Riew - reactive view basics](https://krasimirtsonev.com/blog/article/riew-reactive-view-intro)\n* [Part 3: Riew - reactive view in patterns](https://krasimirtsonev.com/blog/article/riew-reactive-view-in-patterns)\n\n**🎮 Playgrounds**\n\n* [Online demo](http://poet.krasimir.now.sh/e/QMPvK8DM2s7).\n* Examples\n  * [ToDoMVC](https://github.com/krasimir/riew/tree/master/examples/todomvc)\n  * [Questionnaire app](https://github.com/krasimir/riew/tree/master/examples/questionnaire)\n  * [Counter](http://poet.krasimir.now.sh/e/gnv7EDgydsQ#App.js)\n  * [Random cat](http://poet.krasimir.now.sh/e/exoE5zyxQhl)\n\n---\n\n**Table of contents**\n\n- [Concepts](#concepts)\n  - [Routines \u0026amp; channels](#routines-amp-channels)\n  - [Riews](#riews)\n  - [Application state](#application-state)\n  - [PubSub](#pubsub)\n- [API](#api)\n  - [chan](#chan)\n  - [buffer](#buffer)\n    - [buffer.fixed()](#bufferfixed)\n    - [buffer.fixed(n)](#bufferfixedn)\n    - [buffer.sliding(n)](#bufferslidingn)\n    - [buffer.dropping(n)](#bufferdroppingn)\n  - [fixed(n)](#fixedn)\n  - [sliding(n)](#slidingn)\n  - [dropping(n)](#droppingn)\n  - [go](#go)\n    - [Stopping a routine](#stopping-a-routine)\n    - [Restarting the routine](#restarting-the-routine)\n    - [What you can yield](#what-you-can-yield)\n    - [Injecting external dependencies](#injecting-external-dependencies)\n  - [put](#put)\n  - [sput](#sput)\n  - [take](#take)\n  - [stake](#stake)\n  - [close](#close)\n  - [sclose](#sclose)\n  - [read](#read)\n  - [sread](#sread)\n  - [listen](#listen)\n  - [unsubscribing](#unsubscribing)\n  - [unsubAll](#unsuball)\n  - [call](#call)\n  - [fork](#fork)\n  - [sleep](#sleep)\n  - [stop](#stop)\n  - [timeout](#timeout)\n  - [merge](#merge)\n  - [state](#state)\n    - [selectors](#selectors)\n    - [mutators](#mutators)\n  - [riew](#riew)\n    - [Riew routines](#riew-routines)\n    - [Externals](#externals)\n    - [Channels and state](#channels-and-state)\n  - [react](#react)\n  - [register](#register)\n  - [use](#use)\n  - [reset](#reset)\n  - [constants](#constants)\n- [Inspiration](#inspiration)\n\n## Concepts\n\n### Routines \u0026 channels\n\nImagine that you need to transfer messages between two functions in your system. They don't know about each other. With Riew you can use a _channel_ to connect and synchronize them. We can put and take messages from that channel. Consider the following example:\n\n```js\nconst ch = chan();\n\ngo(function * A() {\n  const name = yield take(ch);\n  yield put(ch, `Hey ${name}, how are you?`);\n});\ngo(function * B() {\n  yield put(ch, \"Steve\");\n  console.log(yield take(ch));\n});\n```\n\nWe have two generator functions (routines) `A` and `B`. They start synchronously one after each other. However, `A` is paused (blocked) at the `yield take` statement because it wants to read from the channel `ch` but there is nothing inside. Then routine `B` puts `Steve` and routine `A` resumes back. Now `B` is blocked because it tries to read from the same channel. `Steve` is already consumed by the other routine so we are again at the same blocking situation. `B` waits till `A` puts `Hello Steve, how are you?`. At the end the log happens and we see the message into the console.\n\nThis is the basic idea behind [CSP](https://en.wikipedia.org/wiki/Communicating_sequential_processes). We have channels that are used for communication and synchronization. By default the channel operations are blocking. Putting can't happen until there is someone to take and the opposite - taking can't happen until there is someone to put. This is the behavior of the standard non-buffered channel or the so called _fixed_ buffer. There are couple of other types and we will learn about them below.\n\nAs for the routines, we may `yield` all sort of things. We may `put`, `take`, `sleep` but we may also `yield` a promise. Then Riew will wait till the promise is resolved and will resume the generator. We may even use the `call` and `fork` helpers to run other routines. 😮\n\n### Riews\n\nThe _riew_ is a combination between _view_ function and routine functions. It's materialized into an object that has `mount`, `update` and `unmount` methods. The routines get started when we mount the riew. They receive a `render` method so we can send data to the view function.\n\n```js\nconst ch = chan();\nconst view = function(props) {\n  console.log(props);\n};\nfunction* A() {\n  const name = yield take(ch);\n  yield put(ch, `Hey ${name}, how are you?`);\n}\nfunction* B({ render }) {\n  yield put(ch, 'Steve');\n  render({ message: yield take(ch) });\n}\n\nconst r = riew(view, A, B);\n\nr.mount();\n```\n\nThis example prints out an object `{ message: \"Hey Steve, how are you?\" }`. As we know from the previous section, `B` routine waits till it receives the message formatted by routine `A`. It sends it to the `view` function by using the `render` function. This code sample illustrates one of the core concept behind this library - keep the view pure and distribute the business logic across routines.\n\nWe may directly send a channel to the `render` function and whatever we `put` inside will reach the view. For example:\n\n```js\nconst view = function (props) {\n  console.log(props);\n}\nfunction * A({ render }) {\n  const ch = chan();\n  render({ name: ch })\n  yield put(ch, 'Martin');\n}\n\nconst r = riew(view, A);\n\nr.mount();\n```\n\nThe result here is `{ name: 'Martin' }`.\n\n_(There is a [React extension](https://github.com/krasimir/riew#react) bundled within the library so if you use React you'll probably never call `mount`, `update` and `unmount` manually. This is done by the library.)_\n\n### Application state\n\nIn the original [CSP](https://en.wikipedia.org/wiki/Communicating_sequential_processes) paper there is no concept of a _state_. At least not in the same way as we use it in JavaScript today. For us _state_ is a value that persist across time. It can be accessed, changed and it is always available. The channels can keep values but they are consumed at some point. Or in other words _taken_ and don't exists as such in the channels anymore.\n\nRiew brings the idea of a state by defining a value that is outside the channels. It can be however accessed and modified by using channels. Imagine the state as a black box with a value and channels for writing and reading that value. Riew follows this idea by allowing the definition of multiple read channels called _selectors_ and multiple write channels called _mutators_. Let's see an example:\n\n```js\n// A state which value is an empty array.\nconst users = state([]);\n\n// Channel for updating the state value.\nconst add = users.mutate(function reducer(currentUsers, newUser) {\n  return [...currentUsers, newUser];\n});\n// Channel for reading the state value.\nconst getUsers = users.select(function mapping(users) {\n  return users.map(({ name }) =\u003e name).join(', ');\n});\n\ngo(function* A() {\n  yield put(add, { name: 'Steve', age: 24 });\n  yield put(add, { name: 'Ana', age: 25 });\n  yield put(add, { name: 'Peter', age: 22 });\n  console.log(yield take(getUsers)); // Steve, Ana, Peter\n});\n```\n\nThe `mutate` method of the state accepts a `reducer` function and returns a channel. Let's say that we put \"foo\" in the channel. The reducer will be called with the current state value followed by \"foo\" string.\n\nThe `select` method returns a channel which we can read from and the value is whatever the `mapping` function returns. That function receives the current state value and returns it. Or maybe just a portion of it. Or perhaps a different representation of the data. Like in our case we return a comma separated list of user names.\n\nA helpful pattern is to use a routine as a mutator. And because the routine may be asynchronous you may block until the mutation is done. Consider the trivial case where we have to get data from remote endpoint and show it to the user.\n\n```js\nconst cat = state(null);\nconst getKitty = cat.mutate(function * () {\n  const { file } = yield fetch('https://aws.random.cat/meow').then(res =\u003e res.json());\n  return file;\n});\n\ngo(function * A() {\n  console.log('I want a kitty.');\n  yield put(getKitty);\n  console.log(`Here we go ${ yield take(cat) }`);\n});\n```\n\nThe routine `A` is blocked on the put to `put(getKitty)`. Our mutator is picked up and makes a request to `https://aws.random.cat/meow`. Once it finishes it mutates the state and replaces `null` with a URL. Then our routine is resumed and we can print that URL.\n\n```js\n\u003e I want a kitty.\n\u003e Here we go https://purr.objects-us-east-1.dream.io/i/W6jh8.jpg\n```\n\nFurther more we can handle the request error inside the mutator and put something else in the `cat` state.\n\n### PubSub\n\nThe [PubSub](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern) pattern is widely used in JavaScript. There are tons of libraries that are using it and it's a de-facto standard these days. I (the author of this library) however think that this pattern doesn't play well with the [CSP](https://en.wikipedia.org/wiki/Communicating_sequential_processes) concepts. I've made couple of tests and tried implementing it with pure CSP concepts but it simply doesn't work as expected. That's because in the PubSub pattern we have a broadcasting system. A system in which the dispatcher of the message doesn't care what happens with the dispatched message. The act of message sending is not a blocking operation. In CSP is quite opposite. When we put something into the channel we are blocked until someone takes it. Also in PubSub we have one-to-many relationship and all the subscribers receive the same message. While in CSP if we hook multiple takers to a channel they'll all receive different messages because once the message is consumed it disappears from the channel and the next taker will read the next message. CSP and PubSub are kind of similar concepts. They both follow the push model and could be used to write code in a reactive way. However, they act differently.\n\nRiew offers PubSub pattern capabilities. They are however added next to the core CSP processes and the developer needs to make a clear separation between the two. Consider the following example:\n\n```js\ngo(function* A() {\n  console.log(`Value: ${yield read(ch)}`);\n});\ngo(function* B() {\n  yield put(ch, 'Foo');\n  console.log('Bar');\n});\n```\n\nThe result of this snippet is only `\"Value: undefined\"`. The [read](https://github.com/krasimir/riew#read) function only **reads** the value but doesn't consume it from the channel. It also resoloves with whatever the channel contains at this exact moment. Above we are getting `undefined` because there is nothing in the channel yet. Also routine `B` stays blocked because there is no [taker](https://github.com/krasimir/riew#take) for the `ch` channel.\n\nBy default `read` (and its standalone version `sread`) is one-shot operation. This means that we aread and move forward. However, we may use the `listen` method and effectively subscribe for values passed to the channel.\n\n```js\nconst ch = chan();\n\nlisten(ch, value =\u003e {\n  console.log(`Value: ${value}`);\n});\n\nsput(ch, 'foo'); // Value: foo\nsput(ch, 'bar'); // Value: bar\nsput(ch, 'moo'); // Value: moo\n```\n\nSo, there is a way to use the PubSub pattern. It's just the difference between _reading_ and _taking_.\n\n## API\n\n### chan\n\n\u003e `chan(id, buff)` or `chan(buff)`\n\nCreates a new channel with ID equal to `id` and buffer equal to `buff`.\n\n* `id` (`String`, optional) - must be unique for your system. If not specified it will be auto-generated by the library.\n* `buff` (`Buffer`, optional) - buffer created by using the [`buffer`](https://github.com/krasimir/riew#buffer) helpers. If not specified `buffer.fixed()` is used.\n\nThe function returns a channel object with the following methods/fields:\n\n* `channel.id` - the ID of the channel.\n* `channel.isActive()` - returns `true` if the channel is in an `OPEN` state.\n* `channel.state()` - returns one of the following: `OPEN`, `CLOSED` or `ENDED`. When the `channel` is `OPEN` we can put and take from it. When it is `CLOSED` every put gets resolved with `CLOSED`. The `take` on a `CLOSED` channel consumes the values left in the channel. If no values the `take` will be resolved with `CLOSED`. When a channel is `ENDED` both `put` and `take` are resolved with `ENDED`.\n* `exportAs(key)` - this is useful when we want to share this channel with the rest of the application without passing the instance around. Check [this](#externals) section for more information.\n\nExample:\n\n```js\nconst ch = chan('FOOBAR');\n\nconsole.log(ch.id); // FOOBAR\nconsole.log(ch.state()); // Symbol(OPEN)\nconsole.log(ch.isActive()); // true\n```\n\n### buffer\n\n#### buffer.fixed()\n\nIt creates a fixed buffer with size 0. The `put` to the channel is blocked until a `take` happens. A `take` is blocked until a `put` happens.\n\nExample:\n\n```js\nconst ch = chan('MYCHANNEL', buffer.fixed());\n\ngo(function * A() {\n  yield put(ch, 'foo');\n});\ngo(function * B() {\n  yield sleep(1000);\n  const value = yield take(ch);\n  console.log(value); // foo\n});\n```\n\n1. Routine A starts and stops at the `yield put`.\n2. Routine B starts and stops at `yield sleep` for one second.\n3. Routine B is resumed and `take`s 'foo' from the channel.\n4. Routine A is resumed and it ends.\n5. Routine B ends with `value` equal to `foo`.\n\n#### buffer.fixed(n)\n\nIt creates a fixed buffer with size `n`. `n` number of puts are non-blocking and the buffer holds the values till they are consumed. The `n + 1` put is blocking.\n\nExample:\n\n```js\nconst ch = chan('MYCHANNEL', buffer.fixed(2));\n\ngo(function* A() {\n  yield put(ch, 'foo');\n  console.log('a');\n  yield put(ch, 'bar');\n  console.log('b');\n  yield put(ch, 'moo');\n  console.log('c');\n});\ngo(function* B() {\n  yield sleep(2000);\n  console.log(yield take(ch));\n  console.log(yield take(ch));\n  console.log(yield take(ch));\n});\n```\n\n1. Routine A starts and we see `\"a\"` and `\"b\"` in the console. It's because we have a buffer with size 2.\n3. Routine B starts and stops at `yield sleep(2000)` for two seconds.\n4. Routine B continues and consumes all the values from the channel including `\"moo\"`.\n\n#### buffer.sliding(n)\n\nSimilar to the fixed buffer except that the `put`s are never blocking. If the buffer is full a new item is added at the end but one item is removed from the beginning.\n\nExample:\n\n```js\nconst ch = chan('MYCHANNEL', buffer.sliding(2));\n\ngo(function * A() {\n  yield put(ch, 'foo');\n  yield put(ch, 'bar');\n  yield put(ch, 'moo');\n  yield put(ch, 'zoo');\n});\ngo(function * B() {\n  yield sleep(2000);\n  console.log(yield take(ch));\n  console.log(yield take(ch));\n});\n```\n\n1. Routine A starts and all the puts happen with no stopping of the generator.\n2. Routine B starts and in the channel we have `[\"moo\", \"zoo\"]`.\n3. Routine B ends and in the console we see `\"moo\"` followed by `\"zoo\"`.\n\n#### buffer.dropping(n)\n\nSimilar to the fixed buffer except that every `put` outside of the buffer range is not blocking the routing. It resolves with `true` if there is space in the buffer and `false` if not. If there is no space for new values it's simply ignored.\n\nExample:\n\n```js\nconst ch = chan('MYCHANNEL', buffer.dropping(2));\n\ngo(function * A() {\n  yield put(ch, 'foo');\n  yield put(ch, 'bar');\n  yield put(ch, 'moo');\n  yield put(ch, 'zoo');\n});\ngo(function * B() {\n  yield sleep(2000);\n  console.log(yield take(ch));\n  console.log(yield take(ch));\n});\n```\n\n1. Routine A starts and all the puts happen with no stopping of the generator. It's just the last two do nothing.\n2. Routine B starts and in the channel we have `[\"foo\", \"bar\"]`.\n3. Routine B ends and in the console we see `\"foo\"` followed by `\"bar\"`.\n\n### fixed(n)\n\nAlias to `chan(\u003cid\u003e, buffer.fixed(n))`. The `id` is auto-generated. See [here](#bufferfixedn).\n\n### sliding(n)\n\nAlias to `chan(\u003cid\u003e, buffer.sliding(n))`. The `id` is auto-generated. See [here](#bufferslidingn).\n\n### dropping(n)\n\nAlias to `chan(\u003cid\u003e, buffer.dropping(n))`. The `id` is auto-generated. See [here](#bufferdroppingn).\n\n### go\n\n\u003e `go(routine, done, routineArgs)`\n\nRuns a routine.\n\n* `routine` (`Generator`, required) - a generator function\n* `done` (`Function`, optional) - a callback function which is fired when the routine ends.\n* `routineArgs` (`Array\u003cAny\u003e`, optional) - any optional arguments that come as arguments to our generator.\n\nExample:\n\n```js\nconst ch = chan();\n\ngo(\n  function * A(greeting) {\n    const name = yield take(ch);\n    return `${ greeting }, ${ name }`;\n  },\n  (v) =\u003e {\n    console.log(v);\n  },\n  ['Hey']\n);\ngo(function * B() {\n  yield put(ch, 'Pablo')\n});\n```\n\n1. `go` runs a routine `A` with one argument `\"Hey\"`. The routine stops at `yield take(ch)`.\n2. Routine `B` starts and we put `\"Pablo\"` to the channel `ch`.\n3. Routine `A` is resumed and forms its result which is `Hey, Pablo`.\n4. The routine done callback is called and we see the result in the console.\n\n#### Stopping a routine\n\nThe `go` function returns an object that has a `stop` method. Once you call it the routine will be terminated.\n\n```js\nconst routine = go(function * () {\n  yield sleep(1000);\n  // This line will never be executed because\n  // the routine is terminated before it gets resumed.\n  console.log('Never called!'); \n});\n\nroutine.stop(); // \u003c-- this terminates the routine\n```\n\nAnother way to stop the routine is to yield `stop()`. This is not the same as writing `return` because `return` will fire the `done` callback of the routine. `stop()` is about terminating it. In the following example we'll see only `\"done B\"`.\n\n```js\ngo(function * A() {\n  yield stop();\n  console.log('Never called!');\n}, () =\u003e console.log('done A'));\n\ngo(function * B() {\n  return;\n  console.log('Never called!');\n}, () =\u003e console.log('done B'));\n```\n\nThe routine is automatically terminated if it's part of a [riew](https://github.com/krasimir/riew#riew) and the riew is unmounted.\n\n```js\nconst routine = function * () {\n  yield sleep(1000);\n  // This line will never be executed because\n  // the routine is terminated before it gets resumed.\n  console.log('Never called!');\n};\n\nconst r = riew(() =\u003e {}, routine);\n\nr.mount();\nr.unmount(); // \u003c-- this terminates the routine\n```\n\n#### Restarting the routine\n\nRe-running a routine means terminating the current processes and running the generator again.\n\nThe `go` function returns an object that has a `rerun` method. Once you call it the routine will be restarted.\n\n```js\nconst routine = go(function * () {\n  console.log('Hello!');\n  yield sleep(1000);\n  console.log('Bye!');\n});\nroutine.rerun();\n```\n\nWe'll see \"Hello\" twice before seeing \"Bye\", because the routing will be restarted before it gets resumed from the `sleep`.\n\nAnother way to restart the routine is to `return` the `go` function. For example:\n\n```js\ngo(function * () {\n  console.log('Hello!');\n  yield sleep(1000);\n  console.log('Bye!');\n  return go;\n});\n```\n\nThis routine will print `\"Hello!\"`, will wait a second and will print `\"Bye!\"`. And will do that in a endless loop because the generator is restarted every time.\n\n#### What you can yield\n\n* Promise - riew will wait till the promise is resolved and will resume the generator.\n\n```js\nconst routine = go(function * () {\n  const res = yield fetch('https://aws.random.cat/meow');\n  const { file } = yield res.json();\n  console.log(file);\n});\n```\n* [put](https://github.com/krasimir/riew#put)\n* [take](https://github.com/krasimir/riew#take)\n* [read](https://github.com/krasimir/riew#read)\n* [sleep](https://github.com/krasimir/riew#sleep)\n* [stop](https://github.com/krasimir/riew#stop)\n* [close](https://github.com/krasimir/riew#close)\n* [call](https://github.com/krasimir/riew#call)\n* [fork](https://github.com/krasimir/riew#fork)\n\n#### Injecting external dependencies\n\nYou may want to pass something to your routines which is defined far a way from the place where the routine starts. In such cases you can use the `go.with` method:\n\n```js\n// somewhere in your code's entry point\nregister('config', { theme: 'dark' });\n\n// somewhere deep\nconst A = function*({ config, foo }) {\n  console.log(config.theme, foo);\n};\n\ngo.with('config', { foo: 'bar' })(A); // \"dark\", \"bar\"\n```\n\n### put\n\n\u003e `put(channel, anything)`\n\nMeant to be used only inside a routine. It puts items into a channel. Could be blocking. It depends on the channel's [buffer](https://github.com/krasimir/riew#buffer).\n\n* `channel` (One or array of `String`s or a [channel object](https://github.com/krasimir/riew#chan), required) - the channel which we want to put items in.\n* `anything` (`Any`, required) - the item that we want to put into the channel. If we pass an array of channels as first argument then this should be also an array.\n\nThe generator is resumed with `true` if the `put` is successful. `false` in the case of a channel with a dropping [buffer](https://github.com/krasimir/riew#buffer). Or it may return channel [statuses](https://github.com/krasimir/riew#chan) `CLOSED` or `ENDED`.\n\nExample:\n\n```js\nconst ch = chan();\n\ngo(function * () {\n  console.log(yield take(ch));\n})\ngo(function * () {\n  yield put(ch, 'foo');\n});\n```\n\nPutting to multiple channels:\n\n```js\nconst channelA = chan();\nconst channelB = chan();\n\ngo(function*() {\n  console.log(yield take(channelA)); // \"foo\"\n  console.log(yield take(channelB)); // \"foo\"\n});\ngo(function*() {\n  yield put([channelA, channelB], 'foo');\n});\n```\n\nHave in mind that the `put` in this case is released only when we take from both channels.\n\n### sput\n\n\u003e `sput(channel, anything, callback)`\n\nSame as [put](https://github.com/krasimir/riew#put) but it can be used outside of a routine. This function is super handy to make the bridge between Riew and non-Riew code. _(The `s` comes from `standalone`.)_\n\n* `channel` (`String` or a [channel object](https://github.com/krasimir/riew#chan), required) - the channel which we want to put items in.\n* `anything` (`Any`, required) - the item that we want to put into the channel.\n* `callback` (`Function`, optional) - it will be fired when the `put` operation ends.\n\nThe callback may be fired with `true` if the `put` is successful. `false` in the case of a channel with a dropping [buffer](https://github.com/krasimir/riew#buffer). Or with channel [statuses](https://github.com/krasimir/riew#chan) `CLOSED` or `ENDED`.\n\nExample:\n\n```js\nconst ch = chan();\n\ngo(function * () {\n  console.log(yield take(ch));\n});\n\nsput(ch, 'foo', res =\u003e console.log(`Put successful ${ res }`));\n```\n\n### take\n\n\u003e `take(channels, options)`\n\nMeant to be used only inside a routine. It takes an item from a channel. Could be blocking. It depends on the channel's [buffer](https://github.com/krasimir/riew#buffer).\n\n* `channels` (One or array of `String`s or [channel objects](https://github.com/krasimir/riew#chan), required) - the channel which we want to take items from.\n* `options` (`Object`, optional) - additional options for the _take_ operation\n  * `strategy` (`ALL_REQUIRED` or `ONE_OFF`, `ALL_REQUIRED` by default) - if we take from multiple channels this option describes our strategy. Either we wait for all the channels to have values (`ALL_REQUIRED`) or we expect at least one of them to be fulfilled (`ONE_OF`).\n\nThe generator is resumed with the item taken from the channel.\n\nExample:\n\n```js\nconst ch = chan();\n\ngo(function * () {\n  console.log(yield take(ch));\n})\ngo(function * () {\n  yield put(ch, 'foo');\n});\n```\n\nIn case of taking from multiple channels we get an array as a result. If the strategy is `ALL_REQUIRED` (by default) we'll get an array of ordered channel values. For example:\n\n```js\nconst ch1 = chan();\nconst ch2 = chan();\n\ngo(function*() {\n  console.log(yield take([ch2, ch1])); // ['bar', 'foo']\n});\n\nsput(ch1, 'foo');\nsput(ch2, 'bar');\n```\n\n_Notice that we are getting `[\"bar\", \"foo\"]` and not `[\"foo\", \"bar\"]`._\n\nIf we use `ONE_OF` strategy the second element of the array is the index of the matched channel:\n\n```js\nconst ch1 = chan();\nconst ch2 = chan();\n\ngo(function*() {\n  console.log(yield take([ch2, ch1], { strategy: ONE_OF })); // ['foo', 1]\n});\n\nsput(ch1, 'foo');\n```\n\n_The second element of the array is `1`, not 0, because `ch1` is at the second position in the array._\n\n### stake\n\n\u003e `stake(channels, callback, options)`\n\nSame as [take](https://github.com/krasimir/riew#take) but it can be called outside of a routine. This function is super handy to make the bridge between Riew and non-Riew code. The `s` comes from `standalone`.\n\n* `channels` (One or array of `String`s or [channel objects](https://github.com/krasimir/riew#chan), required) - the channel which we want to take items from.\n* `callback` (`Function`, optional) - it will be fired with the item taken from the channel.\n* `options` (`Object`, optional) - additional options for the _take_ operation\n  * `strategy` (`ALL_REQUIRED` or `ONE_OFF`, `ALL_REQUIRED` by default) - if we take from multiple channels this option describes our strategy. Either we wait for all the channels to have values (`ALL_REQUIRED`) or we expect at least one of them to be fulfilled (`ONE_OF`).\n\nThe callback is fired with the item put to the channel. If we take from more then one channel we'll receive an array of values. If we use `ONE_OF` strategy the second argument of the callback is the index of the channel received a value.\n\nExample:\n\n```js\nconst ch = chan();\n\ngo(function * () {\n  yield put(ch, 'foo');\n  yield put(ch, 'bar');\n});\n\nstake(ch, item =\u003e console.log(item));\n```\n\nNotice that this is one-time call. It's not like a [subscription](https://github.com/krasimir/riew#read) to a channel. In the example here we'll see only `\"foo\"` but not `\"bar\"`.\n\n### close\n\n\u003e `close(channel)`\n\nThis function closes a channel and it is meant to be used inside a generator. Which means that the channel's state is set to `CLOSE` or maybe `ENDED`. It depends on the [buffer](https://github.com/krasimir/riew#buffer) strategy.\n\n* `channel` (`String` or a [channel object](https://github.com/krasimir/riew#chan), required) - the channel that we want to close.\n\nExample:\n\n```js\nconst ch = chan();\n\ngo(function * () {\n  console.log(yield take(ch));\n  console.log(yield take(ch));\n  console.log(yield take(ch));\n});\ngo(function * () {\n  yield put(ch, 'foo');\n  yield close(ch);\n});\n```\n\nIn the console we'll see `\"foo\"` followed by two `Symbol(ENDED)`. The routine is paused at the first [take](https://github.com/krasimir/riew#take). `put` resumes it with the value of `\"foo\"` and the routine gets paused at the second take. The `close` call closes the channel and releases all the pending takes. Each of the next takes will result with either `CLOSE` ro `ENDED` depending of the value of the channel's [buffer](https://github.com/krasimir/riew#buffer). Every [put](https://github.com/krasimir/riew#put) to a `CLOSED` or `ENDED` channel is resolved with a channel status immediately.\n\n### sclose\n\n\u003e `sclose(channel)`\n\nThis function is the same as [close](#close) but it's meant to be used outside of a routine.\n\n* `channel` (`String` or a [channel object](#chan), required) - the channel that we want to close.\n\nExample:\n\n```js\nconst ch = chan();\n\ngo(function * () {\n  console.log(yield take(ch));\n  console.log(yield take(ch));\n  console.log(yield take(ch));\n});\n\nsput(ch, 'foo');\nsclose(ch);\n```\n\nIn the console we'll see `\"foo\"` followed by two `Symbol(ENDED)`. The routine is paused at the first [take](https://github.com/krasimir/riew#take). `sput` resumes it with the value of `\"foo\"` and the routine gets paused at the second take. The `close` call closes the channel and releases all the pending takes. Each of the next takes will result with either `CLOSE` ro `ENDED` depending of the value of the channel's [buffer](https://github.com/krasimir/riew#buffer). Every [put](https://github.com/krasimir/riew#put) to a `CLOSED` or `ENDED` channel is resolved with a channel status immediately.\n\n### read\n\n\u003e `read(sourceChannels, options)`\n\nIt's meant to be used only inside a routine and it _reads_ from a channel/s. `yield read(channel)` is not blocking the [put](https://github.com/krasimir/riew#put) on the other side of the channel and it's not consuming the value. It is always resolved no mather if the channel has value or not.\n\n* `sourceChannels` (array of channels or a single channel, required) - the source channel which we will be subscribed to. In case of multiple channels the default behavior is that the subscriber is notified only when all the source channels have values. Check out the `strategy` option below.\n* `options` (`Object`, optional) - additional options for the reading\n  * `strategy` (`ONE_OF` or `ALL_REQUIRED`, default to `ALL_REQUIRED`) - base on that the library decided wether to wait for all the source channels or not. If set to `ONE_OF` it will resolve the read as soon as some of the sources receives a value.\n\nExample:\n\n```js\nconst ch = chan();\n\ngo(function * A() {\n  console.log(yield read(ch)); // undefined\n  console.log('done'); // done\n});\ngo(function * B() {\n  yield put(ch, 'foo'); // \u003c-- never resolved\n  yield put(ch, 'bar'); // \u003c-- never called\n});\n```\n\nIf we run this code we'll see `\"undefined\"` followed by `\"done\"`. The second put in routine `B` never happens because the first put is blocked. We need a [take](https://github.com/krasimir/riew#take) to release it. The `read` in routine `A` doesn't consume the value of the channel, just reads it so can't unblock `B`. And because routine `A` starts first we still have nothing (`undefined`) in the channel.\n\n### sread\n\n\u003e `sread(sourceChannels, to, options)`\n\nSame as [read](#read) but it's meant to be used outside of a routine. \n\n* `sourceChannels` (array of channels or a single channel, required) - the source channel which we will be subscribed to. In case of multiple channels the default behavior is that the subscriber is notified only when all the source channels have values. Check out the `strategy` option below.\n* `to` (`Channel`, or a function, required) - the values from the `sourceChannels` are piped to the passed channel. If a function, that function is called with the values.\n* `options` (`Object`, optional) - additional options for the reading\n  * `strategy` (`ONE_OF` or `ALL_REQUIRED`, default to `ALL_REQUIRED`) - base on that the library decided wether to wait for all the source channels or not. If set to `ONE_OF` it will resolve the read as soon as some of the sources receives a value.\n\nExample:\n\n```js\nconst ch = sliding();\n\nsput(ch, 'foo');\nsread(ch, value =\u003e {\n  console.log(value); // foo\n});\nstake(ch, value =\u003e {\n  console.log(value);\n});\n```\n\n`stake` is successfully resolved because `sread` is not consuming the value of the `ch` channel.\n\n### listen\n\n\u003e `listen(sourceChannels, to, options)`\n\nMeant to be used outside of a routine. It subscribes for `sourceChannels` and runs the `to` function (or pushes to `to` channel) every time when there is an input.\n\n* `sourceChannels` (array of channels or a single channel, required) - the source channel which we will be subscribed to. In case of multiple channels the default behavior is that the subscriber is notified only when all the source channels have values. Check out the `strategy` option below.\n* `to` (`Channel`, or a function, required) - the values from the `sourceChannels` are piped to the passed channel. If a function, that function is called with the values.\n* `options` (`Object`, optional) - additional options for the reading\n  * `strategy` (`ONE_OF` or `ALL_REQUIRED`, default to `ALL_REQUIRED`) - base on that the library decided wether to wait for all the source channels or not. If set to `ONE_OF` it will resolve the read as soon as some of the sources receives a value.\n  * `initialCall` (`Boolean`, optional, `false` by default) - by default the subscription doesn't apply until there is a new value to the `sourceChannels`. If we set this to `true` we will get one initial call.\n\nThe most basic example is when we want to get values pushed to a channel into a regular JavaScript function.\n\n```js\nconst ch = chan();\n\nlisten(ch, value =\u003e {\n  console.log(value);\n});\n\nsput(ch, 'foo');\nsput(ch, 'bar');\n```\n\nThe result is `foo` followed by `bar`.\n\nWe can listen to more then one channel. By default `listen` waits by default to all of the channels to be filled with values. Then it calls the callback.\n\n```js\nconst ch1 = chan();\nconst ch2 = chan();\n\nlisten([ch1, ch2], function subscriber(value) {\n  console.log(value);\n});\n\nsput(ch1, 'foo');\nsput(ch2, 'bar');\nsput(ch2, 'moo');\nsput(ch1, 'zoo');\n```\n\nThe first `sput` doesn't trigger the `subscriber`. After the second one we get `[\"foo\", \"bar\"]` as a value. Then we get `[\"foo\", \"moo\"]` and at the end `[\"zoo\", \"moo\"]`. The third and the fourth `sput` trigger the subscriber because then both channels have received values. Also notice that if we have more then one channel the value in the subscriber comes as an array.\n\nAnother interesting use case for `listen` is when we use a `ONE_OF` strategy and receive the input from each of the source channels:\n\n```js\nconst chA = chan();\nconst chB = chan();\n\nlisten([chA, chB], (v, idx) =\u003e {\n  console.log(v, idx);\n}, { strategy: ONE_OF });\n\nsput(chA, 'foo');\nsput(chB, 'bar');\nsput(chA, 'moo');\n```\n\nThe result of this script will be `\"foo 0\"` followed by `\"bar 1\"` followed by `\"moo 0\"`. It's because the library is not waiting for all the channels to have values but triggers the callback immediately when it receives a value.\n\n### unsubscribing\n\nIf we have used `listen` to subscribe to channel values we may want to unsubscribe. In this case we may use the function returned by `listen`. For example:\n\nExample:\n\n```js\nconst source = chan();\nconst subscriber = chan();\nconst unsubscribe = listen(source, subscriber);\n\ngo(function * () {\n  console.log(yield take(subscriber));\n  unsubscribe();\n  console.log(yield take(subscriber));\n});\n\nsput(source, 'foo');\nsput(source, 'bar');\n```\n\nWe see only `\"foo\"` because after the first `take` we remove the subscription. Then there is no one to `put` into the `subscriber` channel.\n\n### unsubAll\n\n\u003e `unsubAll(sourceChannel)`\n\nRemoves all the subscriptions made to the `sourceChannel`. If we use [listen](https://github.com/krasimir/riew#listen) we effectively create a subscription. We may want to stop it.\n\n* `sourceChannel` (`Channel`, required) - the source channel that we subscribed to.\n\nExample:\n\n```js\nconst source = chan();\nconst subscriber = chan();\n\nlisten(source, subscriber);\n\ngo(function * () {\n  console.log(yield take(subscriber));\n  unsubAll(source);\n  console.log(yield take(subscriber));\n});\n\nsput(source, 'foo');\nsput(source, 'bar');\n```\n\nWe see only `\"foo\"` because after the first `take` we remove all the subscription.\n\n### call\n\n\u003e `call(routine, ...routineArgs)`\n\nIt runs another routine and it's meant to be used only inside a routine.\n\n* `routine` (`Generator`, required) - a generator function\n* `routineArgs` (`Any`, optional) - any optional arguments that come as arguments to our generator.\n\nExample:\n\n```js\nfunction * A(name) {\n  return `Hey, ${ name }!`;\n}\n\ngo(function * B() {\n  console.log(yield call(A, 'Ana')); // Hey, Ana!\n});\n```\n\nNotice that the routine `B` is paused until routine `A` finishes.\n\n### fork\n\n\u003e `fork(routine, ...routineArgs)`\n\nLike [call](https://github.com/krasimir/riew#call) but it's not pausing the main routine. Meant to be used only inside a routine.\n\n* `routine` (`Generator`, required) - a generator function\n* `routineArgs` (`Any`, optional) - any optional arguments that come as arguments to our generator.\n\nExample:\n\n```js\nconst ch = chan();\n\nfunction * fillName(name) {\n  yield sleep(1000);\n  yield put(ch, name);\n}\n\ngo(function * printName() {\n  yield fork(fillName, 'Ana');\n  console.log('Hey,'); // \u003c- we see \"Hey,\" immediately because `fork` is not-blocking operation\n  console.log(`How are you ${ yield take(ch) }!`); // How are you Ana!\n});\n```\n\nNotice that the routine `printName` is not paused when we `yield fork`.\n\n### sleep\n\n\u003e `sleep(interval)`\n\nIt's meant to be used only inside a routine. It pauses the routine for a given time.\n\n* `interval` (`Number`, required) - milliseconds\n\nExample:\n\n```js\ngo(function * () {\n  console.log('A');\n  yield sleep(2000); // \u003c-- two seconds delay\n  console.log('A');\n});\n```\n\n### stop\n\n\u003e `stop()`\n\nIt's meant to be used only inside a routine. It terminates the routine.\n\nExample:\n\n```js\nconst answer = 42;\ngo(function * () {\n  console.log('A');\n  if (answer === 42) {\n    yield stop();\n  }\n  console.log('Never called!');\n});\n```\n\n### timeout\n\n\u003e `timeout(interval)`\n\nIt creates a channel that will close after a given interval of time.\n\n* `interval` (`Number`, required) - milliseconds\n\nExample:\n\n```js\nconst ch = timeout(1000);\n\ngo(function * () {\n  yield put(ch, 'foo');\n  yield put(ch, 'bar');\n  yield put(ch, 'moo');\n})\ngo(function * () {\n  console.log(yield take(ch));\n  yield sleep(2000);\n  console.log(yield take(ch));\n  console.log(yield take(ch));\n});\n```\n\nWe'll see `\"foo\"` and then two seconds later two `Symbol(ENDED)`. That's because the channel is closed after a second and the two takes after the `sleep` are operating with an `ENDED` channel.\n\n### merge\n\n\u003e `merge(...sourceChannels)`\n\nReturns a channel that contains the values from all the source channels. Have in mind that internally this function registers a taker.\n\n* `sourceChannels` (`Channels`, required) - one or many channels\n\nExample:\n\n```js\nconst chA = chan();\nconst chB = chan();\nconst ch = merge(chA, chB);\n\ngo(function * () {\n  console.log(yield take(ch)); // foo\n  console.log(yield take(ch)); // bar\n  console.log(yield take(ch)); // moo\n  console.log(yield take(ch)); // zoo\n});\ngo(function * () {\n  yield put(chA, 'foo');\n  yield put(chB, 'bar');\n  yield put(chB, 'moo');\n  yield put(chA, 'zoo');\n});\n```\n\nThe behavior of this function could be replicated by using [listen](https://github.com/krasimir/riew#listen). The difference between these two variants is that `merge` consumes values from channels while `listen` is just reading from them.\n\n### state\n\n\u003e `state(initialValue)`\n\nAs we mentioned in the [Application state](https://github.com/krasimir/riew#application-state) section, the CSP pattern doesn't really offer state capabilities. The channels can keep value over time, but once someone takes it the channel is empty and the next taker will receive another value. Riew builds on top of the CSP idea by saying that the state lives outside of the pattern and we use channels to get and set the value.\n\n* `initialValue` (`Any`, optional) - if not specified the initial value is `undefined`.\n\nReturns a state object with the following fields:\n\n* `DEFAULT` - a [sliding](#bufferslidingn) channel. When we read from it, we will receive the value of the state. When we put to it will update the state value.\n* `select(selector, onError)` - creates a [sliding](#bufferslidingn) channel for reading. `selector` is a function or a routine that receives the current value and must return another value. `onError` is here to handle errors coming from the `selector` function.\n* `mutate(reducer, onError)` - creates a [sliding](#bufferslidingn) channel for writing. `reducer` is a function or a routine that receives the current state value and an item that is put to the channel. It must return a new version of the state. `onError` is here to handle errors produced by the `reducer`.\n* `destroy` - closes all the created channels\n* `set(value)` - a synchronous way to set the value of the state. It puts the new value to all sliding channels created from the state.\n* `get()` - a synchronous way to get the value of the state without involving channels.\n\nExample:\n\n```js\nconst counter = state(0);\n\ngo(function * () {\n  console.log(yield take(counter.READ)) // 0\n  yield put(counter.WRITE, 42);\n  console.log(yield take(counter.READ)) // 42\n});\n```\n\n`0` in this example is the initial value of the state. Then we have two built-in channels - `counter.READ` and `counter.WRITE`. The putting and taking from this channel usually happens synchronously. If we are about to use those channels we may skip writing `.READ` and `.WRITE` and simply use the state object directly. Like so:\n\n```js\nconst counter = state(0);\n\ngo(function*() {\n  console.log(yield read(counter.DEFAULT)); // 0\n  yield put(counter.DEFAULT, 42);\n  console.log(yield read(counter.DEFAULT)); // 42\n});\n```\n\nNotice that we are using `read` and not `take` to get the value out of the default channel. If we use `take` the value will be consumed and every next `take` will be blocking. This though doesn't mean that the value disappears. It is still in the `counter` object and we can get it via `counter.get()`. Also notice that all the channels created out of a state are using a [sliding](#bufferslidingn) buffer. This is to have non-blocking puts.\n\n#### selectors\n\n\u003e `state.select(selector, onError)`\n\nThe read channels are called selectors and are defined by using the `select` method of the state.\n\n```js\nconst name = state('Samantha');\n\nconst up = name.select(str =\u003e str.toUpperCase());\nconst lower = name.select(str =\u003e str.toLowerCase());\nconst message = name.select(str =\u003e `My name is ${str}`);\n\ngo(function*() {\n  console.log(yield read(up)); // SAMANTHA\n  console.log(yield read(lower)); // samantha\n  console.log(yield read(message)); // My name is Samantha\n});\n```\n\n#### mutators\n\n\u003e `state.mutate(reducer, onError)`\n\nThe write channels are called mutators and are defined by using the `mutate` method of the state.\n\n```js\nconst counter = state(0);\n\nconst add = counter.mutate((current, n) =\u003e current + n);\nconst double = counter.mutate(current =\u003e current * 2);\n\ngo(function*() {\n  yield put(add, 10);\n  yield put(double);\n  console.log(yield read(counter)); // 20\n});\n```\n\nHave in mind that the `reducer` can be a routine (generator function) and as such may be asynchronous.\n\n### riew\n\n\u003e `riew(view, ...routines)`\n\nCreates a _riew_ based on the given `view` function and `routines` generator functions.\n\n* `view` (`Function`, required) - a view function that will receive the data.\n* `routines` (one or many routines, optional) - routines that will start when the riew is mounted and terminate when the riew is unmounted.\n\nReturns an object with the following methods:\n\n* `mount(props)` - `props` is an object that will reach our view.\n* `unmount()` - unmounts the riew. Performs clean up operations.\n* `update(props)` - `props` is an object that will reach our view.\n* `with(...externals)` - a list of externals to be injected into the view and the routines. Check the [Externals](https://github.com/krasimir/riew#externals) section for more details.\n\nExample\n\n```js\nfunction view(props) {\n  console.log(props);\n}\nfunction * A({ render }) {\n \trender({ foo: 'bar' });\n}\nfunction * B({ render }) {\n \trender({ moo: 'zoo' });\n}\n\nconst r = riew(view, A, B);\n\nr.mount();\n```\n\nThe `view` functions gets called once with `{ foo: \"bar\", moo: \"zoo\" }`.\n\n#### Riew routines\n\nThe Riew routines that are passed to the `riew` function receive an object with the following properties:\n\n* `render` - must be called with an object. That object reaches the `view`. Have in mind that multiple `render` calls are batched into a single `view` call via micro task. This `render` function is the main tool for updating the view.\n* `state` - alias to [state](https://github.com/krasimir/riew#state). All the states created with this alias will be destroyed when the riew is unmounted. It's recommended if you have local for the riew state to created it via this function so it gets cleaned up when the riew is unmounted.\n* `fixed`, `sliding`, `dropping` - alias to [channel methods](https://github.com/krasimir/riew#fixedn). All the channels created with this aliases will be destroyed when the riew is unmounted. It's recommended if you have local for the riew channel to created it via this functions so it gets cleaned up when the riew is unmounted.\n* `props` - a props channel of the riew. It gives you access to the object that is passed to `mount` and `updated` methods.\n* the Riew routines also receive the [externals](https://github.com/krasimir/riew#externals) injected into the riew (if any)\n\nWe have to clarify what we mean by \"object that reaches the `view`\". It's a JavaScript object literal that contains keys and values. This may be raw data but may be also a Riew [channel](https://github.com/krasimir/riew#chan) or a [state](https://github.com/krasimir/riew#state). In this cases the view gets whatever is the data in the channel or whatever is the value of the state. Keep reading, there're more examples in the [Channels and state](https://github.com/krasimir/riew#channels-and-state) section.\n\n#### Externals\n\nVery often we'll need _services_ and configuration to reach our riews. The library provides a mechanism for dealing with such dependencies. We'll better understand it by checking the following example:\n\n```js\nconst answerService = {\n  getAnswer() {\n    return new Promise(done =\u003e setTimeout(() =\u003e done(42), 1000));\n  }\n}\nconst ch = chan();\nconst view = function (data) {\n  console.log(data);\n}\nconst routine = function * ({ answer, service }) {\n  const number = yield service.getAnswer();\n  yield put(answer, number);\n}\nconst r = riew(view, routine).with({\n  answer: ch,\n  service: answerService\n});\n\nr.mount();\n```\n\n`answerService` is a silly example of a service with a single method that does some async job. We then have a channel and our `view` followed by our `routine`. Notice the usage of the `with` method when defining the riew. We are saying that we want to initiate our riew with two props - `answer` and `service`. The `view` function gets called twice with the following props:\n\n```\n{ service: {...} }\n{ service: {...}, answer: 42 }\n```\n\nThe `answerService` reaches the `view` and the routine as it is because Riew have no idea what it is. However the `answer` is treated differently. The library sees that this is a channel and subscribes the `view` to items coming from that channel. The routine receives the channel as it is and we can `put` to it. At the end of the snippet the riew is mounted, the routine starts, we get the async call happening and we push the number to the channel.\n\nThe `with` method is one of the ways to subscribe our views to channels. Every channel has an `exportAs` method which saves a reference to the channel in a global registry. We may then use the `with` method to access that same channel:\n\n```js\n// At the top level of your application.\nconst ch = chan().exportAs('my-channel');\n\n// Somewhere in the UI layer.\nconst view = function(data) {\n  console.log(data);\n};\nconst r = riew(view).with('my-channel');\n\nr.mount();\n\n// At some point we put data to the channel.\nsput(ch, 'Simon');\n```\nThe result of this snippet is `{ name: \"Simon\" }` in the console. It works like that because our riew gets subscribed for new values coming to the channel.\n\nThe `with` helper could be also used to inject stuff that are pushed to a [global registry](https://github.com/krasimir/riew#register) directly.\n\n```js\nregister('config', { theme: 'dark' });\n\nconst r = riew(function (props) {\n  console.log(`Selected theme: ${ props.config.theme }`); // Selected theme: dark\n}).with('config');\n\nr.mount();\n```\n\nSame as in `exportAs` instead of an object we just have to pass the key of the dependency.\n\n#### Channels and state\n\nThe channels and state are integral part of the riew concept. We use them to push data to the view, synchronize processes and communicate events. Our riews internally check what is behind the data before passing it to the view.\n\n* If we have a channel the riew creates a subscription using [listen](https://github.com/krasimir/riew#listen) and re-renders the view with the value send to the channel.\n* If we have a state the riew again creates a subscription but to the default read channel of the state.\n\n```js\nconst view = function(data) {\n  console.log(data);\n};\nconst routine = function*({ render }) {\n  const counter = state(0);\n\n  const inc = counter.mutate(n =\u003e n + 1);\n  const sel = counter.select(n =\u003e `value is ${n}`);\n  setInterval(() =\u003e sput(inc, 1), 1000);\n  render({ counter, message: sel });\n};\nconst r = riew(view, routine);\n\nr.mount();\n```\n\nIn this example we are creating a state that keeps a number. We also have two channels one of which is created by the state's `mutate` method - `inc`. What we send to the view is the state `counter` and a message (check the [state](https://github.com/krasimir/riew#state) section to see what `select` and `mutate` mean in details). The result of this code is that our `view` is called every second with `{counter: \u003cnumber\u003e, value: \"value is \u003cnumber\u003e\"}`.\n\nOur riews are bound to channels and we control what the view renders by putting data to those channels.\n\n### react\n\n\u003e `react.riew(reactComponent, ...routines)`\n\nSame as [riew](https://github.com/krasimir/riew#riew) but for the view instead of a regular function takes a React component.\n\n* `reactComponent` (`React component`, required) - React component (class or a function)\n* `routines` (one or many routines, optional) - routines that will start when the riew is mounted and terminates when the riew is unmounted.\n\n`react.riew` returns another React component.\n\nExample:\n\n```js\nfunction Greeting(props) {\n  return \u003cp\u003eHey, { props.name }.\u003c/p\u003e\n}\nfunction * routine({ render }) {\n  render({ name: 'Ana' });\n}\n\nconst Component = react.riew(Greeting, routine);\n\nReactDOM.render(\u003cComponent /\u003e, document.querySelector('#output'));\n```\n\nThe `Component` constant here is indeed a React component but it is also a [riew](https://github.com/krasimir/riew#riew). So it has a [with](https://github.com/krasimir/riew#externals) method. The `Greeting` component is the same as the `view` function in all the other examples above.\n\n### register\n\n\u003e `register(key, dependency)`\n\nTogether with [use](#use) and [with](#injecting-external-dependencies) this function implements a mechanism for dealing with dependencies. `register` defines an entry in  a _globally_ available registry and [use](#use) is accessing that entry. Once we define something with `register` we may inject it into our riews with the [with](#externals) method.\n\n* `key` (`String`, required) - a string the uniquely identifies the dependency\n* `dependency` (`Any`, required) - this could be a primitive like string or a number but could be also instance of a service or a state object.\n\nExample:\n\n```js\nregister('config', { theme: 'dark' });\n\nconst r = riew(function (props) {\n  console.log(`Selected theme: ${ props.config.theme }`); // Selected theme: dark\n}).with('config');\n\nr.mount();\n```\n\n### use\n\n\u003e `use(key)`\n\nIt gives you access to the dependency registered using the [register](#register) function. This function is useful if we want to use something in our routines.\n\n* `key` (`String`, required) - the key identifier of the dependency.\n\n```js\nregister('config', { theme: 'dark' });\n\nconst view = function (props) {\n  console.log(`Selected theme: ${ props.theme }`); // Selected theme: dark\n};\nconst routine = function * ({ render }) {\n  const config = use('config');\n  render({ theme: config.theme });\n}\nconst r = riew(view, routine).with('config');\n\nr.mount();\n```\n\n### reset\n\n\u003e `reset()`\n\nIt resets all the internal structures of the library. This function is useful while writing unit tests for your riews or routines. Riew for example keeps track of all the channels that we are creating. And in the unit tests we don't want to have conflicts of channel IDs. So we call the `reset` function before each test.\n\n### constants\n\nWe have three constants which we can use together with the [state](#chan) method of the channel to identify what's the current state.\n\n* `OPEN` - channel is open\n* `CLOSED` - channel is closed but we it still has items in it.\n* `ENDED` - channel is closed and empty\n\nThe two options for [subscription](#listen) strategies:\n\n* `ALL_REQUIRED` - notify the subscriber only if all the source channels have value.\n* `ONE_OF` - notify the subscriber if at least one of the source channels have value.\n\n## Inspiration\n\n* [CSP](https://en.wikipedia.org/wiki/Communicating_sequential_processes)\n* [core.async](https://github.com/clojure/core.async)\n* [Go](https://golang.org/)\n* [Redux](https://redux.js.org/)\n* [redux-saga](https://redux-saga.js.org/)\n* [JS-CSP](https://github.com/js-csp/js-csp)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrasimir%2Friew","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkrasimir%2Friew","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrasimir%2Friew/lists"}