{"id":13394438,"url":"https://github.com/kriskowal/gtor","last_synced_at":"2025-05-15T11:07:02.540Z","repository":{"id":19530229,"uuid":"22777776","full_name":"kriskowal/gtor","owner":"kriskowal","description":"A General Theory of Reactivity","archived":false,"fork":false,"pushed_at":"2017-12-04T19:07:25.000Z","size":4345,"stargazers_count":3055,"open_issues_count":13,"forks_count":112,"subscribers_count":122,"default_branch":"master","last_synced_at":"2025-04-14T18:12:58.951Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/kriskowal.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2014-08-09T03:14:46.000Z","updated_at":"2025-04-08T18:51:16.000Z","dependencies_parsed_at":"2022-08-07T09:15:24.734Z","dependency_job_id":null,"html_url":"https://github.com/kriskowal/gtor","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kriskowal%2Fgtor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kriskowal%2Fgtor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kriskowal%2Fgtor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kriskowal%2Fgtor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kriskowal","download_url":"https://codeload.github.com/kriskowal/gtor/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248933340,"owners_count":21185460,"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":[],"created_at":"2024-07-30T17:01:19.737Z","updated_at":"2025-04-14T18:13:03.221Z","avatar_url":"https://github.com/kriskowal.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","frontend","Resources","others","Book","Articles"],"sub_categories":["General"],"readme":"\n# A General Theory of Reactivity\n\n*A work in progress.*\n\n*There are three recordings of a [presentation][] of A General Theory of\nReactivity: [OSCON][], [MediterraneaJS][], [MidwestJS][]. The [presentation][]\nincludes figures and animations not presented here.*\n\n[presentation]: https://github.com/kriskowal/gtor/blob/master/presentation/README.md\n[OSCON]: https://www.youtube.com/watch?v=2p51PE1MZ8U\n[MediterraneaJS]: https://vimeo.com/144478375\n[MidwestJS]: https://www.youtube.com/watch?v=R9CGieinKVo\n\nIn the context of a computer program, reactivity is the process of receiving\nexternal stimuli and propagating events.\nThis is a rather broad definition that covers a wide variety of topics.\nThe term is usually reserved for systems that respond in turns to sensors,\nschedules, and above all, problems that exist between the chair and keyboard.\n\nThe field of reactivity is carved into plots ranging from \"reactive programming\"\nto the subtly distinct \"*functional* reactive programming\", with acrage set\naside for \"self adjusting computation\" and with neighbors like \"bindings\" and\n\"operational transforms\".\nAdherents favor everything from \"continuation passing style\" to \"promises\", or\nthe related concepts of \"deferreds\" and \"futures\".\nOther problems lend themselves to \"observables\", \"signals\", or \"behaviors\", and\neveryone agrees that \"streams\" are a good idea, but \"publishers\" and\n\"subscribers\" are distinct.\n\nIn 1905, Einstein created a theory of special relativity that unified the\nconcepts of space and time, and went on to incorporate gravity, to bring the\nthree fundamentals of physical law into a single model.\nTo a similar end, [various][Rx] minds in the field of reactivity have been\nconverging on a model that unifies at least promises and observables.\n\n[Rx]: https://github.com/Reactive-Extensions/RxJS/blob/aaebfe8962cfa06a6c80908d079928ba5b800c66/doc/readme.md\n\n|              | **Singular**         | **Plural**              |\n| :----------: | :------------------: | :---------------------: |\n| **Spatial**  | Value                | Iterable\u0026lt;Value\u0026gt;   |\n| **Temporal** | Promise\u0026lt;Value\u0026gt; | Observable\u0026lt;Value\u0026gt; |\n\nHowever, this description fails to capture all of the varigated concepts of\nreactivity.\nRather, Rx conflates all reactive primitives into a single Observable type that\ncan perform any role.\nJust as an array is an exemplar of an entire taxonomy of collections, promises,\nstreams, and observables are merely representatives of their class of reactive\nprimitives.\nAs the common paraphrase of Einstein goes, everything should be made as simple\nas possible, but no simpler.\n\n\n## Concepts\n\nFor the purpose of discussion, we must establish a vocabulary.\nSome of these names have a long tradition, or at least some precedent in\nJavaScript.\nSome are disputed, borrowed, or fabricated.\n\nA **value** is **singular** and **spatial**.\nIt can be accessed or modified.\nIf we break this atom, it will fall into two parts: the **getter** and the\n**setter**.\nData flows in one direction, from the setter to the getter.\n\nThe duality of a getter and a setter, a producer and a consumer, or a writer and\na reader, exists in every reactive primitive.\nErik Meijer shows us the parallelism and reflection that exists between various\ntypes of reactive duals in his [keynote for Lang.NEXT, 2014][EM].\n\n[EM]: http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote-Duality\n\nSingular is as opposed to **plural** or multiple.\nAn array, or generally any collection, contains multiple values.\nAn **iterator** is a plural getter.\nA **generator** and iterator form the plural dual for values in space.\n\nSpatial is as opposed to **temporal**.\nReactivity is about time.\n\nA **promise** is a getter for a single value from the past or the future.\nIn JavaScript, and in the language E from which we borrowed the concept, the\ncorresponding setter is a **resolver**.\nCollectively, an asynchronous value is a **deferred**.\n\nIf a promise is the temporal analogue of a value, a **stream** is the temporal\nanalogue of an array.\nThe producer side of a stream is a writer and the consumer side is a reader.\nA **reader** is an asynchronous iterator and a **writer** is an asynchronous\ngenerator.\n\n\n| Interface  |               |          |          |\n| ---------- | ------------- | -------- | -------- |\n| Value      | Value         | Singular | Spatial  |\n| Getter     | Getter        | Singular | Spatial  |\n| Setter     | Setter        | Singular | Spatial  |\n| Array      | Value         | Plural   | Spatial  |\n| Iterator   | Getter        | Plural   | Spatial  |\n| Generator  | Setter        | Plural   | Spatial  |\n| Deferred   | Value         | Singular | Temporal |\n| Promise    | Getter        | Singular | Temporal |\n| Resolver   | Setter        | Singular | Temporal |\n| Stream     | Value         | Plural   | Temporal |\n| Reader     | Getter        | Plural   | Temporal |\n| Writer     | Setter        | Plural   | Temporal |\n\n\n### Singular and plural\n\nAn observer can subscribe to eventually see the value of a promise.\nThey can do this before or after the promise has a value.\nAny number of observers can subscribe multiple times and any single observer can\nsubscribe to the same promise multiple times.\n\nAs such, promises model dependency.\nPromises and resolvers can be safely distributed to any number of producers and\nconsumers.\nIf multiple producers race to resolve a promise, the experience of each producer\nis indistinguishable regardless of whether they won or lost the race.\nLikewise, if multiple consumers subscribe to a promise, the experience of each\nconsumer is indistinguishable.\nOne consumer cannot prevent another consumer from making progress.\nInformation flows in one direction.\nPromises make reactive programs more robust and composable.\n\nPromises are **broadcast**.\n\nThe law that no consumer can interfere with another consumer makes it impossible\nfor promises to abort work in progress.\nA promise represents a result, not the work leading to that result.\n\nA **task** has mostly the same form and features as a promise, but is unicast by\ndefault and can be cancelled.\nA task can have only one subscriber, but can be explicitly forked to create a\nnew task that depends on the same result.\nEach subscriber can unsubscribe, and if all subscribers have unsubscribed and no\nfurther subscribers can be introduced, a task can abort its work.\n\nTasks are **unicast** and therefore cancelable.\n\nSee the accompanying sketch of a [task][] implementation.\n\n[task]: http://kriskowal.github.io/gtor/docs/task\n\nThere is also an esoteric difference between a promise and a future.\nPromise resolvers accept either a value or a promise and will recursively unwrap\ntransitive promises for promises.\nIn most if not all strongly typed languages, this behavior makes it hard if not\nimpossible to infer the type of a promise.\nA **future** is a promise’s strongly typed alter ego, which can take advantage\nof type inference to avoid having to explicitly cast the type of a promise.\n\nPromises, tasks, and futures are three variations of a singular reactive value.\nThey vary by being either broadcast or unicast, or by being suitable for strong\nor weak type systems.\n\n\n### Plural and temporal\n\nThere are many plural reactive value types.\nEach has a different adaptation for dealing with limited resources.\n\nA **stream** has many of the same constraints as an array.\nImagine a plane with space and time.\nIf you rotate an array from the space axis to the time axis, it would become a\nstream.\nThe order is important, and every value is significant.\n\nConsumers and producers are unlikely to process values at the same rate.\nIf the consumer is faster than the producer, it must idle between receiving\nvalues.\nIf a producer is faster than their corresponding consumer, it must idle between\nsending values.\n\nThis pushing and pulling is captured by the concept of **pressure**.\nOn the producer side, a vacuum stalls the consumer and a pressure sends values\nforward.\nOn the consumer side, a vacuum draws values forward and pressure, often called\n**back pressure**, stalls the producer.\nPressure exists to ensure that every value transits the setter to the getter.\n\nSince the consumer of a stream expects to see every value, streams are **unicast**\nlike tasks.\nAs they are unicast they are also cancelable.\nStreams are a cooperation between the reader and the writer and information\nflows both ways.\nData flows forward, acknowledgements flow backward, and either the consumer or\nproducer can terminate the flow.\n\nAlthough a stream is unicast, it is certainly possible to branch a stream into\nmultiple streams in a variety of ways.\nA fork in a stream is an operator that ensures that every value gets sent to\neach of an array of consumers.\nThe slowest of the forks determines the pressure, so the pressure of a fork can\nonly be higher than that of a single consumer.\nThe simpler strategy of providing a stream to multiple consumers produces a\n“round robin” load balancing effect, where each consumer receives an exclusive,\npossibly random, portion of the stream.\nThe pressure of a shared stream can only be lower than that of a single\nconsumer.\n\nIn the following example, the `map` operator creates two new streams from a\nsingle input stream.\nThe slow map will see half as many values as the fast map.\nThe slow map will consume and produce five values per second, and the fast map\nwill consume and produce ten, sustaining a maximum throughput of fifteen values\nper second if the original stream can produce values that quickly.\nIf the original stream can only produce ten or less values per second, the\nvalues will be distributed fairly between both consumers.\n\n```js\nvar slow = stream.map(function (n) {\n    return Promise.return(n).delay(200);\n});\nvar fast = stream.map(function (n) {\n    return Promise.return(n).delay(100);\n});\n```\n\nIn contrast, **publishers** and **subscribers** are **broadcast**.\nInformation flows only one direction, from the publishers to the subscribers.\nAlso, there is no guarantee of continuity.\nThe publisher does not wait for a subscriber and the subscriber receives\nwhatever values were published during the period of their subscription.\nA stream would buffer all values produced until the consumer arrives.\n\nWith *time series data*, values that change over time but belie\nthe same meaning, order and integrity may not be important.\nFor example, if you were bombarded with weather forecasts, you could discard\nevery report except the one you most recently received.\nAlternately, consider a value that represents the current time.\nSince the current time is always changing, it would not be meaningful, much less\npossible, to respond every moment it changes.\n\nTime series data comes in two varieties: **discrete** and **continuous**.\nDiscrete values should be **pushed** whereas continuous values should be\n**pulled** or **polled**.\n(If a homophone is a disaster, what are synonymous homophones?)\n\nThe current time or temperature are examples of **continuous behaviors**.\nAnimation frames and morse code are examples of **discrete signals**.\n\n\n## Primitives\n\nLet us consider each primitive in detail.\nSince the temporal primitives have spatial analogies, and since some of these\nspatial primitives are relatively new to JavaScript, we will review these first.\n\n\n### Iterators\n\nAn iterator is an object that allows us to lazily but synchronously consume\nmultiple values.\nIterators are not new to JavaScript, but there is a new standard forming at time\nof writing.\n\nIterators implement a `next()` method that returns an object that may have a\n`value` property, and may have a `done` property.\nAlthough the standard does not give this object a name, we will call it an\n**iteration**.\nIf the iterator has produced the entirety of a sequence, the `done` property of\nthe iteration will be `true`.\nGenerator functions return iterators that expand on this basic definition.\nThe `value` of a non-final iteration corresponds to a `yield` expression and the\n`value` of a `done` iteration corresponds to a `return` expression.\n\nIterators are an interface with many implementations.\nThe canonical iterator yields the values from an array.\n\n```js\nvar iterator = iterate([1, 2, 3]);\nvar iteration = iterator.next();\nexpect(iteration.value).toBe(1);\niteration = iterator.next();\nexpect(iteration.value).toBe(2);\niteration = iterator.next();\nexpect(iteration.value).toBe(3);\niteration = iterator.next();\nexpect(iteration.done).toBe(true);\n```\n\nWhat distinguishes an iterator from an array is that it is **lazy**.\nAn iterator does not necessarily end.\nWe can have iterators for non-terminating sequences, like counting or the\nfibonacci sequence.\nThe `range` function produces a sequence of values within an interval and\nseparated by a stride.\n\n```js\nfunction range(start, stop, step) {\n    return {next: function () {\n        var iteration;\n        if (start \u003c stop) {\n            iteration = {value: start};\n            start += step;\n        } else {\n            iteration = {done: true};\n        }\n        return iteration;\n    }};\n}\n```\n\nIf the `stop` value of the range is `Infinity`, the iterator will have no end,\nand will never produce a `done` iteration.\nUnlike an array, an indefinite iterator consumes no more memory than an empty\none.\n\n```js\nvar iterator = range(0, Infinity, 1);\nexpect(iterator.next().value).toBe(0);\nexpect(iterator.next().value).toBe(1);\nexpect(iterator.next().value).toBe(2);\n// ...\n```\n\nThe **eager** equivalent would produce an array, but would only work for bounded\nintervals since it must create an exhaustive collection in memory before\nreturning.\n\n```js\nfunction range(start, stop, step) {\n    var result = [];\n    while (start \u003c stop) {\n        result.push(start);\n        start += step;\n    }\n    return result;\n}\n\nexpect(range(0, 6, 2)).toEqual([0, 2, 4]);\n```\n\nIterators may have alternate implementations of some methods familiar from\narrays.\nFor example, `forEach` would walk the iterator until it is exhausted.\n`map` would produce a new iterator of values passed through some transform,\nwhile `filter` would produce a new iterator of the values that pass a test.\nAn iterator can support `reduce`, which would exhaust the iteration, but\n`reduceRight` would be less sensible since iterators only walk forward.\nIterators may also have some methods that are unique to their character, like\n`dropWhile` and `takeWhile`.\n\nWe can save time and space by implementing pipelines with iterators instead of\narrays.\nThe following example can be interpreted as either eager or lazy, depending on\nwhether `range` returns an array or an iterator.\nIf we start with an array, `map` will create another array of 1000 values and\n`filter` will create another large array.\nIf we start with an iterator, we will never construct an array of any size,\ninstead percolating one value at a time as the reducer pulls them from the\nfilter, as the filter pulls them from the mapping, and as the mapping pulls them\nfrom the range.\n\n```js\nrange(0, 1000, 1)\n.map(function (n) {\n    return n * 2;\n})\n.filter(function (n) {\n    return n % 3 !== 0;\n})\n.reduce(function (a, b) {\n    return a + b;\n})\n```\n\n\n### Generator Functions\n\nConsider the eager and lazy `range` function implementations.\nWe lose a certain clarity when we convert the array range maker into an iterator\nrange maker.\nGenerator functions alleviate this problem by offering a way to express\niterations procedurally, with a lazy behavior.\n\nA JavaScript engine near you may already support generator functions.\nThe syntax consists of adding an asterisk to the function declaration and using\n`yield` to produce iterations.\nCalling a generator function does not execute the function, but instead sets up\na state machine to track where we are in the function and returns an iterator.\nWhenever we ask the iterator for an iteration, the state machine will resume the\nexecution of the function until it produces an iteration or terminates.\n\n```js\nfunction *range(start, stop, step) {\n    while (start \u003c stop) {\n        yield start;\n        start += step;\n    }\n}\n\nvar iterator = range(0, Infinity, 1);\nexpect(iterator.next().value).toBe(0);\nexpect(iterator.next().value).toBe(1);\nexpect(iterator.next().value).toBe(2);\n// ...\n```\n\nNotice that the range generator function restores and perhaps even exceeds the\nclarity of the range array maker.\n\nCalling `next` has three possible outcomes.\nIf the iterator encounters a `yield`, the iteration will have a `value`.\nIf the iterator runs the function to either an express or implied `return`, the\niteration will have a `value` and `done` will be true.\nIf the iterator runs to an explicit return, this terminal iteration carries the\nreturn value.\nIf the generator function throws an error, this will propagate out of `next()`.\n\nGenerators and iterators are **unicast**.\nThe consumer expects to see every value from the producer.\nSince generators and iterators cooperate, information flows both forward as\nvalues, and backward as requests for more values.\n\nHowever, the consumer can send other information back to the producer.\nThe `next` method, familiar from basic iterators, gains the ability to determine\nthe value of the `yield` expression from which the generator resumes.\nAs a trivial example, consider a generator that echoes whatever the consumer\nrequests.\n\n```js\nfunction *echo() {\n    var message;\n    while (true) {\n        console.log(\"tick\");\n        message = yield message;\n        console.log(\"tock\");\n    }\n}\n\nvar iterator = echo();\nconsole.log(iterator.next());\n// tick\n// { value: undefined, done: false }\nconsole.log(iterator.next(\"Hello\"));\n// tock\n// tick\n// { value: \"Hello\", done: false }\nconsole.log(iterator.next(\"Goodbye\"));\n// tock\n// tick\n// { value: \"Goodbye\", done: false }\n```\n\nWe must prime the generator because it does not begin with a `yield`.\nWe advance the state machine to the first `yield` and allow it to produce the\ninitial, undefined message and halts at the yield expression.\nWe then send a \"Hello\".\nThis resumes the generator, storing the message, continuing into another\niterator, retreiving the same message, yielding it back to the caller.\n\nThis communication back and forth between the consumer and producer foreshadows\nthe ability of stream readers to push back on stream writers.\n\nAdditionally, the iterator gains a `throw` method that allows the iterator to\nterminate the generator by causing the `yield` expression to raise the given\nerror.\nThe error will unravel the stack inside the generator.\nIf the error unravels a try-catch-finally block, the catch block may handle the\nerror, leaving the generator in a resumable state if the returned iteration is\nnot `done`.\nIf the error unravels all the way out of the generator, it will pass into the\nstack of the `throw` caller.\n\nThe iterator also gains a `return` method that causes the generator to resume as\nif from a `return` statement, regardless of whether it actually paused at a\n`yield` expression.\nLike a thrown error, this unravels the stack, executing finally blocks, but not\ncatch blocks.\n\nAs such, like `next`, the `throw` and `return` methods may either return an\niteration, done or not, or throw an error.\nThis foreshadows the ability of a stream reader to prematurely stop a stream\nwriter.\n\n```js\niterator.throw(new Error(\"Do not want!\"));\n```\n\nNote that in Java, [iterators][Java Iterator] have a `hasNext()` method.\nThis is not implementable for generators owing to the [Halting Problem][].\nThe iterator must try to get a value from the generator before the generator can\nconclude that it cannot produce another value.\n\n[Java Iterator]: http://docs.oracle.com/javase/7/docs/api/java/util/Iterator.html\n[Halting Problem]: http://en.wikipedia.org/wiki/Halting_problem\n\n\n### Generators\n\nThere is no proposal for a standard generator, but for the sake of completeness,\nif an array iterator consumes an array, an array generator would lazily produce\none.\nAn array generator object would implement `yield` as a method with behavior\nanalogous to the same keyword within a generator function.\nThe `yield` method would add a value to the array.\n\n```js\nvar array = [];\nvar generator = generate(array);\ngenerator.yield(10);\ngenerator.yield(20);\ngenerator.yield(30);\nexpect(array).toEqual([10, 20, 30]);\n```\n\n\nSince ECMAScript 5, at Doug Crockford’s behest, JavaScript allows keywords to be\nused for property names, making this parallel between keywords and methods\npossible.\nA generator might also implement `return` and `throw` methods, but a meaningful\nimplementation for an array generator is a stretch of the imagination.\nAlthough an array generator is of dubious utility, it foreshadows the interface\nof asynchronous generators, for which meaningful implementations of `return` and\n`throw` methods are easier to obtain, and go on to inform a sensible design for\nasynchronous generator functions.\n\n\n### Asynchronous Values\n\nThe asynchronous analogue of a getter is a promise.\nEach promise has a corresponding resolver as its asynchronous setter.\nCollectively the promise and resolver are a deferred value.\n\nThe salient method of a promise is `then`, which creates a new promise for the\nresult of a function that will eventually observe the value of the promise.\nIf a promise were plural, the `then` method might be called `map`.\nIf you care to beg an esoteric distinction, it might be called `map` if the\nobserver returns a value and `flatMap` if the observer returns a promise.\nThe `then` method of a promise allows either.\n\n```js\nvar promiseForThirty = promiseForTen.then(function (ten) {\n    return ten + 20;\n})\n```\n\nPromises can also have a `done` method that observes the value but does not\nreturn a promise nor captures the result of the observer.\nAgain, if a promise were plural, the `done` method might be called `forEach`.\n\n```js\npromiseForTen.done(function (ten) {\n});\n```\n\nThe `then` method also supports a second function that would observe whether the\ninput promise radiates an exception, and there is a `catch` method to use as a\nshorthand if you are only interested in catching errors.\n\n```js\npromise.then(onreturn, onthrow);\npromise.catch(onthrow);\n```\n\nAt this point, the design described here begins to differ from the standard\n`Promise` proposed for ECMAScript 6, arriving in browsers at time of writing.\nThe purpose of these differences is not to propose an alternative syntax, but to\nreinforce the relationship between a promise and its conceptual neighbors.\n\nA resolver is the singular analogue of a generator.\nRather than yielding, returning, and throwing errors, the resolver can only\nreturn or throw.\n\n```js\nresolver.return(10);\nresolver.throw(new Error(\"Sorry, please return during business hours.\"));\n```\n\nWith the standard promise, a free `resolve` function is sufficient and ergonomic\nfor expressing both of these methods.\n`resolver.return(promise)` is equivalent to `resolve(promise)`.\n`resolver.return(10)` is equivalent to `resolve(10)` or\n`resolve(Promise.resolve(10))`since non-promise values are automatically boxed\nin an already-fulfilled promise.\n`resolver.throw(error)` is equivalent to `resolve(Promise.reject(error))`.\nIn all positions, `resolve` is the temporal analogue of `return` and `reject` is\nthe temporal analogue of `throw`.\nSince promises as we know them today bridged the migration gap from ECMAScript 3\nto ECMAScript 6, it was also necessary to use non-keywords for method names.\n\nA deferred value can be deferred further by resolving it with another promise.\nThis can occur either expressly through the resolver, or implicitly by returning\na promise as the result of a observer function.\n\n```js\nvar authenticated = getUsernameFromConsole()\n.then(function (username) {\n    return Promise.all([\n       getUserFromDatabase(username),\n       getPasswordFromConsole()\n    ])\n    .then(function ([user, password]) {\n        if (hash(password) !== user.passwordHash) {\n            throw new Error(\"Can't authenticate because the password is invalid\");\n        }\n    })\n})\n```\n\nThe `then` method internally creates a new deferred, returns the promise, and\nlater forwards the return value of the observer to the resolver.\nThis is a sketch of a `then` method that illustrates this adapter.\nNote that we create a deferred, use the resolver, and return the promise.\nThe adapter is responsible for catching errors and giving the consumer an\nopportunity to do further work or to recover.\n\n```js\nPromise.prototype.then = function Promise_then(onreturn, onthrow) {\n    var self = this;\n    var deferred = Promise.defer();\n    var resolver = deferred.resolver;\n    this.done(function (value) {\n        if (onreturn) {\n            try {\n                resolver.return(onreturn(value));\n            } catch (error) {\n                resolver.throw(error);\n            }\n        } else {\n            resolver.return(value);\n        }\n    }, function (error) {\n        if (onthrow) {\n            try {\n                resolver.return(onthrow(value));\n            } catch (error) {\n                resolver.throw(error);\n            }\n        } else {\n            resolver.throw(error);\n        }\n    });\n    return deferred.promise;\n```\n\nThe standard `Promise` does not reveal `Promise.defer()`.\nInstead, it is hidden by `then` and by the `Promise` constructor, which elects\nto hide the deferred object and the resolver object, instead \"revealing\" the\n`resolve` and `reject` methods as free arguments to a setup function, furthering\nthe need to give these functions names that are not keywords.\n\n```js\nvar promise = new Promise(function (resolve, reject) {\n    // ...\n});\n```\n\nWith a promise, information flows only from the first call to a resolver method\nto all promise observers, whether they are registered before or after the\nresolution.\n\nWith a task, information flows from the first call to a resolver method to the\nfirst call to an observer method, regardless of their relative order, but one\nkind of information can flow upstream.\nThe observer may unsubscribe with an error.\nThis is conceptually similar to throwing an error back into a generator from an\niterator and warrants the same interface.\n\n```js\ntask.throw(new Error(\"Never mind\"));\n```\n\nThis interface foreshadows its plural analogue: streams.\n\n\n### Asynchronous Functions\n\nGenerator functions have existed in other languages, like Python, for quite some\ntime, so folks have made some clever uses of them.\nWe can combine promises and generator functions to emulate asynchronous\nfunctions.\nThe key insight is a single, concise method that decorates a generator, creating\nan internal \"promise trampoline\".\nAn asynchronous function returns a promise for the eventual return value, or the\neventual thrown error, of the generator function.\nHowever, the function may yield promises to wait for intermediate values on its\nway to completion.\nThe trampoline takes advantage of the ability of an iterator to send a value\nfrom `next` to `yield`.\n\n```js\nvar authenticated = Promise.async(function *() {\n    var username = yield getUsernameFromConsole();\n    var user = getUserFromDatabase(username);\n    var password = getPasswordFromConsole();\n    [user, password] = yield Promise.all([user, password]);\n    if (hash(password) !== user.passwordHash) {\n        throw new Error(\"Can't authenticate because the password is invalid\");\n    }\n})\n```\n\nMark Miller’s [implementation][Async] of the `async` decorator is succinct and\ninsightful.\nWe produce a wrapped function that will create a promise generator and proceed\nimmediately.\nEach requested iteration has three possible outcomes: yield, return, or throw.\nYield waits for the given promise and resumes the generator with the eventual\nvalue.\nReturn stops the trampoline and returns the value, all the way out to the\npromise returned by the async function.\nIf you yield a promise that eventually throws an error, the async function\nresumes the generator with that error, giving it a chance to recover.\n\n[Async]: http://wiki.ecmascript.org/doku.php?id=strawman:async_functions#reference_implementation\n\n```js\nPromise.async = function async(generate) {\n    return function () {\n        function resume(verb, argument) {\n            var result;\n            try {\n                result = generator[verb](argument);\n            } catch (exception) {\n                return Promise.throw(exception);\n            }\n            if (result.done) {\n                return result.value;\n            } else {\n                return Promise.return(result.value).then(donext, dothrow);\n            }\n        }\n        var generator = generate.apply(this, arguments);\n        var donext = resume.bind(this, \"next\");\n        var dothrow = resume.bind(this, \"throw\");\n        return donext();\n    };\n}\n```\n\nAs much as JavaScript legitimizes the async promise generators by supporting\nreturning and throwing, now that Promises are part of the standard, the powers\nthat sit on the ECMAScript standards committee are contemplating special `async`\nand `await` syntax for this case.\nThe syntax is inspired by the same feature of C#.\n\n```js\nvar authenticate = async function () {\n    var username = await getUsernameFromConsole();\n    var user = getUserFromDatabase(username);\n    var password = getPasswordFromConsole();\n    [user, password] = await Promise.all([user, password]);\n    return hash(password) === user.passwordHash;\n})\n```\n\nOne compelling reason to support special syntax is that `await` may have higher\nprecedence than the `yield` keyword.\n\n```js\nasync function addPromises(a, b) {\n    return await a + await b;\n}\n```\n\nBy decoupling **async functions** from **generator functions**, JavaScript opens\nthe door for **async generator functions**, foreshadowing a **plural** and\n**temporal** getter, a standard form for readable streams.\n\n\n### Promise Queues\n\nConsider an asynchronous queue.\nWith a conventional queue, you must put a value in before you can take it out.\nThat is not the case for a promise queue.\nJust as you can attach an observer to a promise before it is resolved, with a\npromise queue, you can get a promise for the next value in order before that\nvalue has been given.\n\n```js\nvar queue = new Queue();\nqueue.get().then(function (value) {\n    console.log(value);\n})\nqueue.put(\"Hello, World!\");\n```\n\nLikewise of course you can add a value to the queue before observing it.\n\n```js\nvar queue = new Queue();\nqueue.put(\"Hello, World!\");\nqueue.get().then(function (value) {\n    console.log(value);\n})\n```\n\nAlthough promises come out of the queue in the same order their corresponding\nresolutions enter, a promise obtained later may settle sooner than another\npromise.\nThe values you put in the queue may themselves be promises.\n\n```js\nvar queue = new Queue();\nqueue.get().then(function () {\n    console.log(\"Resolves later\");\n});\nqueue.get().then(function () {\n    console.log(\"Resolves sooner\");\n});\nqueue.put(Promise.delay(100));\nqueue.put();\n```\n\nA promise queue qualifies as an asynchronous collection, specifically a\ncollection of results: values or thrown errors captured by promises.\nThe queue is not particular about what those values mean and is a suitable\nprimitive for many more interesting tools.\n\n| Interface     |         |        |          |\n| ------------- | ------- | ------ | -------- |\n| PromiseQueue  | Value   | Plural | Temporal |\n| queue.get     | Getter  | Plural | Temporal |\n| queue.put     | Setter  | Plural | Temporal |\n\nThe implementation of a promise queue is sufficiently succinct that there’s no\nharm in embedding it here.\nThis comes from Mark Miller's [Concurrency Strawman][] for ECMAScript and is a\npart of the Q library, exported by the `q/queue` module.\nInternally, a promise queue is an asynchronous linked list that tracks the\n`head` promise and `tail` deferred.\n`get` advances the `head` promise and `put` advances the `tail` deferred.\n\n```js\nmodule.exports = PromiseQueue;\nfunction PromiseQueue() {\n    if (!(this instanceof PromiseQueue)) {\n        return new PromiseQueue();\n    }\n    var ends = Promise.defer();\n    this.put = function (value) {\n        var next = Promise.defer();\n        ends.resolve({\n            head: value,\n            tail: next.promise\n        });\n        ends.resolve = next.resolve;\n    };\n    this.get = function () {\n        var result = ends.promise.get(\"head\");\n        ends.promise = ends.promise.get(\"tail\");\n        return result;\n    };\n}\n```\n\n[Concurrency Strawman]: http://wiki.ecmascript.org/doku.php?id=strawman:concurrency\n\nThe implementation uses methods defined in a closure.\nRegardless of how this is accomplished, it is important that it be possible to\npass the free `get` function to a consumer and `put` to a producer to preserve\nthe principle of least authority and the unidirectional flow of data from\nproducer to consumer.\n\nSee the accompanying sketch of a [promise queue][] implementation.\n\n[promise queue]: http://kriskowal.github.io/gtor/docs/promise-queue\n\nA promise queue does not have a notion of termination, graceful or otherwise.\nWe will later use a pair of promise queues to transport iterations between\n**streams**.\n\n\n### Semaphores\n\nSemaphores are flags or signs used for communication and were precursors to\ntelegraphs and traffic lights.\nIn programming, semaphores are usually used to synchronize programs that share\nresources, where only one process can use a resource at one time.\nFor example, if a process has a pool of four database connections, it would use\na semaphore to manage that pool.\n\nTypically, semaphores are used to block a thread or process from continuing\nuntil a resource becomes available.\nThe process will \"down\" the semaphore whenever it enters a region where it needs\na resource, and will \"up\" the semaphore whenever it exits that region.\nThe terminology goes back to raising and lowering flags.\nYou can imagine your process as being a train and a semaphore as guarding the\nentrance to a particular length of track.\nYour process stops at the gate until the semaphore goes up.\n\nOf course, in a reactive program, we don’t block.\nInstead of blocking, we return promises and continue when a promise resolves.\nWe can use a promise as a non-blocking mutex for a single resource, and a\npromise queue as a non-blocking semaphore for multiple resources.\n\nIn this example, we establish three database connections that are shared by a\nfunction that can be called to do some work with the first available connection.\nWe get the resource, do our work, and regardless of whether we succeed or fail,\nwe put the resource back in the pool.\n\n```js\nvar connections = new Queue();\nconnections.put(connectToDb());\nconnections.put(connectToDb());\nconnections.put(connectToDb());\n\nfunction work() {\n    return connections.get()\n    .then(function (db) {\n        return workWithDb(db)\n        .finally(function () {\n            connections.put(db);\n        })\n    });\n}\n```\n\n\n### Promise Buffers\n\nConsider another application.\nYou have a producer and a consumer, both doing work asynchronously, the producer\nperiodically sending a value to the consumer.\nTo ensure that the producer does not produce faster than the consumer can\nconsume, we put an object between them that regulates their flow rate: a buffer.\nThe buffer uses a promise queue to transport values from the producer to the\nconsumer, and another promise queue to communicate that the consumer is ready\nfor another value from the producer.\nThe following is a sketch to that effect.\n\n```js\nvar outbound = new PromiseQueue();\nvar inbound = new PromiseQueue();\nvar buffer = {\n    out: {\n        next: function (value) {\n            outbound.put({\n                value: value,\n                done: false\n            });\n            return inbound.get();\n        },\n        return: function (value) {\n            outbound.put({\n                value: value,\n                done: true\n            })\n            return inbound.get();\n        },\n        throw: function (error) {\n            outbound.put(Promise.throw(error));\n            return inbound.get();\n        }\n    },\n    in: {\n        yield: function (value) {\n            inbound.put({\n                value: value,\n                done: false\n            })\n            return outbound.get();\n        },\n        return: function (value) {\n            inbound.put({\n                value: value,\n                done: true\n            })\n            return outbound.get();\n        },\n        throw: function (error) {\n            inbound.put(Promise.throw(error));\n            return outbound.get();\n        }\n    }\n};\n```\n\nThis sketch uses the vernacular of iterators and generators, but each of these\nhas equivalent nomenclature in the world of streams.\n\n-   `in.yield` means “write”.\n-   `in.return` means “close”.\n-   `in.throw` means “terminate prematurely with an error”.\n-   `out.next` means “read”.\n-   `out.throw` means “abort or cancel with an error”.\n-   `out.return` means “abort or cancel prematurely but without an error”.\n\nSo a buffer fits in the realm of reactive interfaces.\nA buffer has an asynchronous iterator, which serves as the getter side.\nIt also has an asynchronous generator, which serves as the setter dual.\nThe buffer itself is akin to an asynchronous, plural value.\nIn addition to satisfying the requirements needed just to satisfy the\ntriangulation between synchronous iterables and asynchronous promises,\nit solves the very real world need for streams that support pressure\nto regulate the rate of flow and avoid over-commitment.\nAn asynchronous iterator is a readable stream.\nAn asynchronous generator is a writable stream.\n\n| Stream            |         |          |              |\n| ----------------- | ------- | -------- | ------------ |\n| Promise Buffer    | Value   | Plural   | Temporal     |\n| Promise Iterator  | Getter  | Plural   | Temporal     |\n| Promise Generator | Setter  | Plural   | Temporal     |\n\nA buffer has a reader and writer, but there are implementations of reader and\nwriter that interface with the outside world, mostly files and sockets.\n\nIn the particular case of an object stream, if we treat `yield` and `next` as\nsynonyms, the input and output implementations are perfectly symmetric.\nThis allows a single constructor to serve as both reader and writer.\nAlso, standard promises use the [Revealing Constructor] pattern, exposing the\nconstructor for the getter side.\nThe standard hides the `Promise.defer()` constructor method behind the scenes,\nonly exposing the `resolver` as arguments to a setup function, and never\nrevealing the `{promise, resolver}` deferred object at all.\nSimilarly, we can hide the promise buffer constructor and reveal the input side\nof a stream only as arguments to the output stream constructor.\n\n```js\nvar reader = new Stream(function (write, close, abort) {\n    // ...\n});\n```\n\nThe analogous method to `Promise.defer()` might be `Stream.buffer()`, which\nwould return an `{in, out}` pair of entangled streams.\n\n[Revealing Constructor]: http://domenic.me/2014/02/13/the-revealing-constructor-pattern/\n\nSee the accompanying sketch of a [stream][] implementation.\n\n[stream]: http://kriskowal.github.io/gtor/docs/stream\n\n\n### Promise Iterators\n\nOne very important kind of promise iterator lifts a spatial iterator into the\ntemporal dimension so it can be consumed on demand over time.\nIn this sketch, we just convert a synchronous `next` method to a method that\nreturns a promise for the next iteration instead.\nWe use a mythical `iterate` function which would create iterators for all\nsensible JavaScript objects and delegate to the `iterate` method of anything\nelse that implements it.\nThere is talk of using symbols in ES7 to avoid recognizing accidental iterables\nas this new type of duck.\n\n```js\nfunction PromiseIterator(iterable) {\n    this.iterator = iterate(iterable);\n}\nPromiseIterator.prototype.next = function () {\n    return Promise.return(this.iterator.next());\n};\n```\n\nThe conversion may seem superfluous at first.\nHowever, consider that a synchronous iterator might, apart from implementing\n`next()`, also implement methods analogous to `Array`, like `forEach`,\n`map`, `filter`, and `reduce`.\nLikewise, an asynchronous iterator might provide analogues to these functions\nlifted into the asynchronous realm.\n\nThe accompanying sketch of a stream constructor implements a method\n`Stream.from`, analogous to ECMAScript 6's own `Array.from`.\nThis function coerces any iterable into a stream, consuming that iterator on\ndemand.\nThis allows us, for example, to run an indefinite sequence of jobs, counting\nfrom 1, doing four jobs at any time.\n\n```js\nStream.from(Iterator.range(1, Infinity))\n.forEach(function (n) {\n    return Promise.delay(1000).thenReturn(n);\n}, null, 4)\n.done();\n```\n\n#### map\n\nFor example, asynchronous `map` would consume iterations and run jobs on each of\nthose iterations using the callback.\nHowever, unlike a synchronous `map`, the callback might return a promise for\nits eventual result.\nThe results of each job would be pushed to an output reader, resulting in\nanother promise that the result has been consumed.\nThis promise not only serves to produce the corresponding output iteration, but\nalso serves as a signal that the job has completed, that the output has been\nconsumed, and that the `map` can schedule additional work.\nAn asynchronous `map` would accept an additional argument that would limit the\nnumber of concurrent jobs.\n\n```js\npromiseIterator.map(function (value) {\n    return Promise.return(value + 1000).delay(1000);\n});\n```\n\n#### forEach\n\nSynchronous `forEach` does not produce an output collection or iterator.\nHowever, it does return `undefined` *when it is done*.\nOf course synchronous functions are implicitly completed when they return,\nbut asynchronous functions are done when the asynchronous value they return\nsettles.\n`forEach` returns a promise for `undefined`.\n\nSince streams are **unicast**, asynchronous `forEach` would return a task.\nIt stands to reason that the asynchronous result of `forEach` on a stream would\nbe able to propagate a cancellation upstream, stopping the flow of data from the\nproducer side.\nOf course, the task can be easily forked or coerced into a promise if it needs\nto be shared freely among multiple consumers.\n\n```js\nvar task = reader.forEach(function (n) {\n    console.log(\"consumed\", n);\n    return Promise.delay(1000).then(function () {\n        console.log(\"produced\", n);\n    });\n})\nvar subtask = task.fork();\nvar promise = Promise.return(task);\n```\n\nLike `map` it would execute a job for each iteration, but by default it would\nperform these jobs in serial.\nAsynchronous `forEach` would also accept an additional argument that would\n*expand* the number of concurrent jobs.\nIn this example, we would reach out to the database for 10 user records at any\ngiven time.\n\n```js\nreader.forEach(function (username) {\n    return database.getUser(username)\n    .then(function (user) {\n        console.log(user.lastModified);\n    })\n}, null, 10);\n```\n\n#### reduce\n\nAsynchronous `reduce` would aggregate values from the input reader, returning a\npromise for the composite value.\nThe reducer would have an internal pool of aggregated values.\nWhen the input is exhausted and only one value remains in that pool, the reducer\nwould resolve the result promise.\nIf you provide a basis value as an argument, this would be used to \"prime the\npump\".\nThe reducer would then start some number of concurrent aggregator jobs, each\nconsuming two values.\nThe first value would preferably come from the pool, but if the pool is empty,\nwould come from the input.\nThe second value would come unconditionally from the input.\nWhenever a job completes, the result would be placed back in the pool.\n\n#### pipe\n\nAn asynchronous iterator would have additional methods like `copy` or `pipe`\nthat would send iterations from this reader to another writer.\nThis method would be equivalent to using `forEach` to forward iterations and\n`then` to terminate the sequence.\n\n```js\niterator.copy(generator);\n// is equivalent to:\niterator.forEach(generator.yield).then(generator.return, generator.throw);\n```\n\nNote that the promise returned by yield applies pressure on the `forEach`\nmachine, pushing ultimately back on the iterator.\n\n#### buffer\n\nIt would have `buffer` which would construct a buffer with some capacity.\nThe buffer would try to always have a value on hand for its consumer by\nprefetching values from its producer.\nIf the producer is faster than the consumer, this can help avoid round trip\nlatency when the consumer needs a value from the producer.\n\n#### read\n\nJust as it is useful to transform a synchronous collection into an iterator and\nan iterator into a reader, it is also useful to go the other way.\nAn asynchronous iterator would also have methods that would return a promise for\na collection of all the values from the source, for example `all`, or in the\ncase of readers that iterate collections of bytes or characters, `join` or\n`read`.\n\n\n#### Remote iterators\n\nConsider also that a reader may be a proxy for a remote reader.\nA promise iterator be easily backed by a promise for a remote object.\n\n```js\nfunction RemotePromiseIterator(promise) {\n    this.remoteIteratorPromise = promise.invoke(\"iterate\");\n}\nRemotePromiseIterator.prototype.next = function (value) {\n    return this.remoteIteratorPromise.invoke(\"next\");\n};\n\nvar remoteReader = remoteFilesystem.invoke(\"open\", \"primes.txt\");\nvar reader = new RemotePromiseIterator(remoteReader);\nreader.forEach(console.log);\n```\n\nApart from `then` and `done`, promises provide methods like `get`, `call`, and\n`invoke` to allow promises to be created from promises and for messages to be\npipelined to remote objects.\nAn `iterate` method should be a part of that protocol to allow values to be\nstreamed on demand over any message channel.\n\n\n### Promise Generators\n\nA promise generator is analogous in all ways to a plain generator.\nPromise generators implement `yield`, `return`, and `throw`.\nThe return and throw methods both terminate the stream.\nYield accepts a value.\nThey all return promises for an acknowledgement iteration from the consumer.\nWaiting for this promise to settle causes the producer to idle long enough for\nthe consumer to process the data.\n\nOne can increase the number of promises that can be held in flight by a promise\nbuffer.\nThe buffer constructor takes a `length` argument that primes the acknowledgement\nqueue, allowing you to send that number of values before having to wait for the\nconsumer to flush.\n\n```js\nvar buffer = new Buffer(1024);\nfunction fibStream(a, b) {\n    return buffer.in.yield(a)\n    .then(function () {\n        return fibStream(b, a + b);\n    });\n}\nfibStream(1, 1).done();\nreturn buffer.out;\n```\n\nIf the consumer would like to terminate the producer prematurely, it calls the\n`throw` method on the corresponding promise iterator.\nThis will eventually propagate back to the promise returned by the generator’s\n`yield`, `return`, or `throw`.\n\n```js\nbuffer.out.throw(new Error(\"That's enough, thanks\"));\n```\n\n\n### Asynchronous Generator Functions\n\nJafar Husain recently [asked the ECMAScript committee][JH1], whether generator\nfunctions and async functions were composable, and if so, how they should\ncompose. (His [proposal][JH2] continues to evolve.)\n\n[JH1]: https://docs.google.com/file/d/0B7zweKma2uL1bDBpcXV4OWd2cnc\n[JH2]: https://github.com/jhusain/asyncgenerator\n\nOne key question is what type an async generator function would return.\nWe look to precedent.\nA generator function returns an iterator.\nA asynchronous function returns a promise.\nShould the asynchronous generator return a promise for an iterator, an iterator\nfor promises?\n\nIf ``Iterator\u003cT\u003e`` means that an iterator implements `next` such that it\nproduces ``Iteration\u003cT\u003e``, the `next` method of an ``Iterator\u003cPromise\u003cT\u003e\u003e``\nwould return an ``Iteration\u003cPromise\u003cT\u003e\u003e``, which is to say, iterations that\ncarry promises for values.\n\nThere is another possibility.\nAn asynchronous iterator might implement `next` such that it produces\n``Promise\u003cIteration\u003cT\u003e\u003e`` rather than ``Iteration\u003cPromise\u003cT\u003e\u003e``.\nThat is to say, a promise that would eventually produce an iteration containing\na value, rather than an iteration that contains a promise for a value.\n\nThis is, an iterator of promises, yielding ``Iteration\u003cPromise\u003cT\u003e\u003e``:\n\n```js\nvar iteration = iterator.next();\niteration.value.then(function (value) {\n    return callback.call(thisp, value);\n});\n```\n\nThis is a promise iterator, yielding ``Promise\u003cIteration\u003cT\u003e\u003e``:\n\n```js\npromiseIterator.next()\n.then(function (iteration) {\n    return callback.call(thisp, iteration.value);\n})\n```\n\nPromises capture asynchronous results.\nThat is, they capture both the value and error cases.\nIf `next` returns a promise, the error case would model abnormal termination of\na sequence.\nIterations capture the normal continuation or termination of a sequence.\nIf the value of an iteration were a promise, the error case would capture\ninability to transport a single value but would not imply termination of the\nsequence.\n\nIn the context of this framework, the answer is clear.\nAn asynchronous generator function uses both `await` and `yield`.\nThe `await` term allows the function to idle until some asynchronous work has\nsettled, and the `yield` allows the function to produce a value.\nAn asynchronous generator returns a promise iterator, the output side of a\nstream.\n\nRecall that an iterator returns an iteration, but a promise iterator returns a\npromise for an iteration, and also a promise generator returns a similar promise\nfor the acknowledgement from the iterator.\n\n```js\npromiseIterator.next()\n.then(function (iteration) {\n    console.log(iteration.value);\n    if (iteration.done) {\n        console.log(\"fin\");\n    }\n});\n\npromiseGenerator.yield(\"alpha\")\n.then(function (iteration) {\n    console.log(\"iterator has consumed alpha\");\n});\n```\n\nThe following example will fetch quotes from the works of Shakespeare, retrieve\nquotes from each work, and push those quotes out to the consumer.\nNote that the `yield` expression returns a promise for the value to flush, so\nawaiting on that promise allows the generator to pause until the consumer\ncatches up.\n\n```js\nasync function *shakespeare(titles) {\n    for (let title of titles) {\n        var quotes = await getQuotes(title);\n        for (let quote of quotes) {\n            await yield quote;\n        }\n    }\n}\n\nvar reader = shakespeare([\"Hamlet\", \"Macbeth\", \"Othello\"]);\nreader.reduce(function (length, quote) {\n    return length + quote.length;\n}, 0, null, 100)\n.then(function (totalLength) {\n    console.log(totalLength);\n});\n```\n\nIt is useful for `await` and `yield` to be completely orthogonal because there\nare cases where one will want to yield but ignore pressure from the consumer,\nforcing the iteration to buffer.\n\nJafar also proposes the existence of an `on` operator.\nIn the context of this framework, the `on` operator would be similar to the\nECMAScript 6 `of` operator, which accepts an iterable, produces an iterator, and\nthen walks the iterator.\n\n```js\nfor (let a of [1, 2, 3]) {\n    console.log(a);\n}\n\n// is equivalent to:\n\nvar anIterable = [1, 2, 3];\nvar anIterator = anIterable[Symbol.iterate]();\nwhile (true) {\n    let anIteration = anIterator.next();\n    if (anIteration.done) {\n        break;\n    } else {\n        var aValue = anIteration.value;\n        console.log(aValue);\n    }\n}\n```\n\nThe `on` operator would operate on an asynchronous iterable, producing an\nasynchronous iterator, and await each promised iteration.\nLook for the `await` in the following example.\n\n```js\nfor (let a on anAsyncIterable) {\n    console.log(a);\n}\n\n// is equivalent to:\n\nvar anAsyncIterator = anAsyncIterable[Symbol.iterate]();\nwhile (true) {\n    var anAsyncIteration = anAsyncIterator.next();\n    var anIteration = await anAsyncIteration;\n    if (anIteration.done) {\n        break;\n    } else {\n        var aValue = anIteration.value;\n        console.log(aValue);\n    }\n}\n```\n\nOne point of interest is that the `on` operator would work for both asynchronous\nand synchronous iterators and iterables, since `await` accepts both values and\npromises.\n\nJafar proposes that the asynchronous analogues of `iterate()` would be\n`observe(generator)`, from which it is trivial to derrive `forEach`, but I\npropose that the asynchronous analogues of `iterate()` would just be\n`iterate()` and differ only in the type of the returned iterator.\nWhat Jafar proposes as the `asyncIterator.observe(asyncGenerator)` method is\neffectively equivalent to synchronous `iterator.copy(generator)` or\n`stream.pipe(stream)`.\nIn this framework, `copy` would be implemented in terms of `forEach`.\n\n```js\nStream.prototype.copy = function (stream) {\n    return this.forEach(stream.next).then(stream.return, stream.throw);\n};\n```\n\nAnd, `forEach` would be implemented in terms of `next`, just as it would be\nlayered on a synchronous iterator.\n\n\n### Observables\n\nThere is more than one way to solve the problem of processor contention or\nprocess over-scheduling.\nStreams have a very specific contract that makes pressurization necessary.\nSpecifically, a stream is intended to transport the entirety of a collection and\nstrongly resembles a spatial collection that has been rotated 90 degrees onto\nthe temporal axis.\nHowever, there are other contracts that lead us to very different strategies to\navoid over-commitment and they depend entirely on the meaning of the data in\ntransit.\nThe appropriate transport is domain specific.\n\nConsider a sensor, like a thermometer or thermocouple.\nAt any given time, the subject will have a particular temperature.\nThe temperature may change continuously in response to events that are not\nsystematically observable.\nSuppose that you poll the thermocouple at one second intervals and place that on\nsome plural, asynchronous setter.\nSuppose that this ultimately gets consumed by a visualization that polls the\ncorresponding plural, asynchronous getter sixty times per second.\nThe visualization is only interested in the most recently sampled value from the\nsensor.\n\nConsider a variable like the position of a scrollbar.\nThe value is discrete.\nIt does not change continuously.\nRather, it changes only in response to an observable event.\nEach time one of these scroll events occurs, we place the position on the\nsetter side of some temporal collection.\nAny number of consumers can subscribe to the getter side and it will push a\nnotification their way.\n\nHowever, if we infer a smooth animation from the discrete scroll positions and\ntheir times, we can sample the scroll position *function* on each animation\nframe.\n\nThese cases are distinct from streams and have interesting relationships with\neach other.\nWith the temperature sensor, changes are **continuous**, whereas with the scroll\nposition observer, the changes are **discrete**.\nWith the temperature sensor, we sample the data at a much lower frequency than\nthe display, in which case it is sufficient to remember the last sensed\ntemperature and redisplay it.\nIf we were to sample the data at a higher frequency than the display, it would\nbe sufficient for the transport to forget old values each time it receives a new\none.\nAlso, unlike a stream, these cases are both well adapted for multiple-producer\nand multiple-consumer scenarios.\n\nAlso unlike streams, one of these concepts pushes data and the other polls or\npulls data.\nA stream has pressure, which is a kind of combined pushing and pulling.\nData is pulled toward the consumer by a vacuum.\nProducers are pushed back by pressure when the vacuum is filled, thus the term:\nback-pressure.\n\nThe discrete event pusher is a Signal.\nThe continuous, pollable is a Behavior.\n\n\n| Interface          |               |      |\n| ------------------ | --------------| ---- |\n| Signal Observable  | Get           | Push |\n| Signal Generator   | Set           | Push |\n| Signal             | Value         | Push |\n| Behavior Iterator  | Get           | Poll |\n| Behavior Generator | Set           | Poll |\n| Behavior           | Value         | Poll |\n\n\n-   TODO make sure this is a summary of the topics in the end:\n\nYet even behaviors have variations like probes, gauges, counters,\nflow gauges, accumulators, flushable accumulators, and rotating counters.\n\n\n### Observables and Signals\n\nA **signal** represents a value that changes over time.\nThe signal is asynchronous and plural, like a stream.\nUnlike a stream, a signal can have multiple producers and consumers.\nThe output side of a signal is an **observable**.\n\nA signal has a getter side and a setter side.\nThe asynchronous getter for a signal is an observable instead of a reader.\nThe observable implements `forEach`, which subscribes an observer to receive\npush notifications whenever the signal value changes.\n\n```js\nsignal.out.forEach(function (value, time, signal) {\n    console.log(value);\n})\n```\n\nThe signal generator is the asynchronous setter.\nLike a stream writer, it implements `yield`.\nHowever, unlike a stream writer, `yield` does not return a promise.\n\n```js\nsignal.in.yield(10);\n```\n\nSignals do not support pressure.\nJust as `yield` does not return a promise, the callback you give to `forEach`\ndoes not accept a promise.\nA signal can only push.\nThe consumer (or consumers) cannot push back.\n\nObservables *also* implement `next`, which returns an iteration that captures\nthe most recently dispatched value.\nThis allows us to poll a signal as if it were a behavior.\n\nSee the accompanying sketch of a [observable][] implementation.\n\n[observable]: http://kriskowal.github.io/gtor/docs/observable\n\nJust as streams relate to buffers, not every observable must be paired with a\nsignal generator.\nA noteworthy example of an external observable is a clock.\nA clock emits a signal with the current time at a regular period and offset.\n\n```js\nvar tick = new Clock({period: 1000});\nvar tock = new Clock({period: 1000, offset: 500});\ntick.forEach(function (time) {\n    console.log(\"tick\", time);\n})\ntock.forEach(function (time) {\n    console.log(\"tock\", time);\n});\n```\n\nSee the accompanying sketch of a [clock][] implementation.\n\n[clock]: http://kriskowal.github.io/gtor/docs/clock\n\nSignals may correspond to system or platform signals like keyboard or mouse\ninput or other external sensors.\nFurthermore, a signal generator might dispatch a system level signal to another\nprocess, for example SIGHUP, which typically asks a daemon to reload its\nconfiguration.\n\n```js\ndaemon.signals.yield(\"SIGHUP\");\n```\n\n\n### Behaviors\n\nA behavior represents a time series value.\nA behavior may produce a different value for every moment in time.\nAs such, they must be **polled** at an interval meaningful to the consumer,\nsince the behavior itself has no inherent resolution.\n\nBehaviors are analogous to Observables, but there is no corresponding setter,\nsince it produces values on demand.\nThe behavior constructor accepts a function that returns the value for a given\ntime.\nAn asynchronous behavior returns promises instead of values.\n\nSee the accompanying sketch of a [behavior][] implementation.\n\n[behavior]: http://kriskowal.github.io/gtor/docs/behavior\n\n\n## Cases\n\n### Progress and estimated time to completion\n\nImagine you are copying the values from a stream into an array.\nYou know how long the array will be and when you started reading.\nKnowing these variables and assuming that the rate of flow is steady, you can\ninfer the amount of **progress** that has been made up to the current time.\nThis is a simple matter of dividing the number of values you have so far\nreceived, by the total number of values you expect to receive.\n\n```js\nvar progress = index / length;\n```\n\nThis is a discrete measurement that you can push each time you receive another\nvalue.\nIt is discrete because it does not change between events.\n\nYou can also infer the average **throughput** of the stream, also a discrete\ntime series.\n\n```js\nvar elapsed = now - start;\nvar throughput = index / elapsed;\n```\n\nFrom progress you can divine an **estimated time of completion**.\nThis will be the time you started plus the time you expect the whole stream to\ntake.\n\n```js\nvar stop = start + elapsed / progress;\nvar stop = start + elapsed / (index / length);\nvar stop = start + elapsed * length / index;\n```\n\nWe could update a progress bar whenever we receive a new value, but frequently\nwe would want to display a smooth animation continuously changing.\nIdeally, progress would proceed linearly from 0 at the start time to 1 at the\nstop time.\nYou could sample progress at any moment in time and receive a different value.\nValues that lack an inherent resolution are *continuous*.\nIt becomes the responsibility of the consumer to determine when to sample,\n**pull** or **poll** the value.\n\nFor the purposes of a smooth animation of a continuous behavior, the frame rate\nis a sensible polling frequency.\nWe can infer a continuous progress time series from the last known estimated time\nof completion.\n\n```js\nvar progress = (now - start) / (estimate - start);\n```\n\n\n## Summary\n\nReactive primitives can be categorized in multiple dimensions.\nThe interfaces of analogous non-reactive constructs including getters, setters,\nand generators are insightful in the design of their asynchronous counterparts.\nIdentifying whether a primitive is singular or plural also greatly informs the\ndesign.\n\nWe can use pressure to deal with resource contention while guaranteeing\nconsistency.\nWe can alternately use push or poll strategies to skip irrelevant states for\neither continuous or discrete time series data with behaviors or signals.\n\nThere is a tension between cancelability and robustness, but we have primitives\nthat are useful for both cases.\nStreams and tasks are inherently cooperative, cancelable, and allow\nbidirectional information flow.\nPromises guarantee that consumers and producers cannot interfere.\n\nAll of these concepts are related and their implementations benefit from mutual\navailability.\nPromises and tasks are great for single result data, but can provide a\nconvenient channel for plural signals and behaviors.\n\nBringing all of these reactive concepts into a single framework gives us an\nopportunity to tell a coherent story about reactive programming, promotes a\nbetter understanding about what tool is right for the job, and obviates the\ndebate over whether any single primitive is a silver bullet.\n\n\n## Further Work\n\nThere are many more topics that warrant discussion and I will expand upon these\nhere.\n\nReservoir sampling can be modeled as a behavior that watches a stream or signal\nand produces a representative sample on demand.\n\nA clock user interface is a good study in the interplay between behaviors,\nsignals, time, and animation scheduling.\n\nDrawing from my experience at FastSoft, we exposed variables from the kernel's\nnetworking stack so we could monitor the bandwidth running through our TCP\nacceleration appliance.\nSome of those variables modeled the number of packets transmitted and the number\nof bytes transmitted.\nThese counters would frequently overflow.\nThere are several interesting ways to architect a solution that would provide\nhistorical data in multiple resolutions, accounting for the variable overflow,\ninvolving a combination of streams, behaviors, and signals.\nI should draw your attention to design aspects of RRDTool.\n\nAn advantage of having a unified framework for reactive primitives is to create\nsimple stories for passing one kind of primitive to another.\nPromises can be coerced to tasks, tasks to promises.\nA signal can be used as a behavior, and a behavior can be captured by a signal.\nSignals can be channeled into streams, and streams can be channeled into\nsignals.\n\nIt is worth exploring in detail how operators can be lifted in each of these\nvalue spaces.\n\nImplementing distributed sort using streams is also a worthy exercise.\n\nAsynchronous behaviors would benefit from an operator that solves the thundering\nherd problem, the inverse of throttling.\n\nHow to implement type ahead suggestion is a great case to explore cancelable\nstreams and tasks.\n\nI also need to discuss how these reactive concepts can propagate operational\ntransforms through queries, using both push and pull styles, and how this\nrelates to bindings, both synchronous and asynchronous.\n\nI also need to compare and contrast publishers and subscribers to the related\nconcepts of signals and streams.\nIn short, publishers and subscribers are broadcast, unlike unicast streams,\nbut a single subscription could be modeled as a stream.\nHowever, a subscriber can typically not push back on a publisher, so how\nresource contention is alleviated is an open question.\n\nRelated to publishing and subscribing, streams can certainly be forked, in which\ncase both branches would put pressure back on the source.\n\nStreams also have methods that return tasks.\nAll of these could propagate estimated time to completion.\nEach of the cases for `all`, `any`, `race`, and `read` are worth exploring.\n\nHigh performance buffers for bytewise data with the promise buffer interface\nrequire further exploration.\n\nImplementing a retry loop with promises and tasks is illustrative.\n\nReactive Extensions (Rx) beg a distinction between [hot and cold][] observables,\nwhich is worth exploring.\nThe clock reference implementation shows one way to implement a signal that can\nbe active or inactive based on whether anyone is looking.\n\n[hot and cold]: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/creating.md#cold-vs-hot-observables\n\nThe research into continuous behaviors and the original idea of Functional\nReactive Programming by [Conal Elliott][] deserves attention.\n\n[Conal Elliott]: http://conal.net/\n\nThe interplay between promises and tasks with their underlying progress behavior\nand estimated time to completion and status signals require further explanation.\nThese ideas need to be incorporated into the sketches of promise and task\nimplementations.\n\n## Glossary\n\n-   accumulator\n-   array\n-   asynchronous\n-   await\n-   behavior\n-   blocking\n-   broadcast\n-   buffer\n-   cancelable\n-   continuous\n-   control\n-   counter\n-   deferred\n-   discrete\n-   flow gauge\n-   future\n-   gauge\n-   getter\n-   getter getter\n-   iterable\n-   iterator\n-   multiple\n-   non-blocking\n-   observable\n-   observer\n-   operation\n-   poll\n-   pressure\n-   probe\n-   promise\n-   publisher\n-   pull\n-   pulse\n-   push\n-   readable\n-   result\n-   retriable\n-   sensor\n-   setter\n-   setter setter\n-   signal\n-   single\n-   sink\n-   spatial\n-   stream\n-   strobe\n-   subscriber\n-   synchronous\n-   task\n-   temporal\n-   throttle\n-   unicast\n-   value\n-   writable\n-   yield\n\n## Acknowledgements\n\nI am grateful to Domenic Denicola, Ryan Paul, and Kevin Smith for reviewing and\nproviding feedback on various drafts of this article.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkriskowal%2Fgtor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkriskowal%2Fgtor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkriskowal%2Fgtor/lists"}