UNPKG

30.9 kBMarkdownView Raw
1<!-- This README.md is automatically generated from source code and files in the /markdown directory. Please DO NOT send pull requests to directly modify this README. Instead, edit the JSDoc comments in source code or the md files in /markdown/. -->
2
3```text
4 _
5__ _____| |_ _ __ ___ __ _ _ __ ___
6\ \/ / __| __| '__/ _ \/ _` | '_ ` _ \
7 > <\__ \ |_| | | __/ (_| | | | | | |
8/_/\_\___/\__|_| \___|\__,_|_| |_| |_|
9```
10<h2 class="site-subtitle">An extremely intuitive, small, and fast<br />functional reactive stream library for JavaScript</h2>
11
12- Only 26 core operators and factories
13- Only ["hot"](https://medium.com/@benlesh/hot-vs-cold-observables-f8094ed53339#.mvzg5e7lf) streams
14- Written in TypeScript
15- Approximately 30 kB in size, when minified
16- On average, faster than RxJS 4, Kefir, Bacon.js, as fast as RxJS 5, and slower than most.js
17- Tailored for [Cycle.js](http://cycle.js.org), or applications with limited use of `subscribe`
18
19![](https://badge-size.herokuapp.com/staltz/xstream/master/dist/xstream.js.svg)
20![](https://badge-size.herokuapp.com/staltz/xstream/master/dist/xstream.min.js.svg?compression=gzip)
21[![ComVer](https://img.shields.io/badge/ComVer-compliant-brightgreen.svg)](https://github.com/staltz/comver)
22[![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?maxAge=2592000)](https://gitter.im/staltz/xstream)
23
24# Example
25
26```js
27import xs from 'xstream'
28
29// Tick every second incremental numbers,
30// only pass even numbers, then map them to their square,
31// and stop after 5 seconds has passed
32
33var stream = xs.periodic(1000)
34 .filter(i => i % 2 === 0)
35 .map(i => i * i)
36 .endWhen(xs.periodic(5000).take(1))
37
38// So far, the stream is idle.
39// As soon as it gets its first listener, it starts executing.
40
41stream.addListener({
42 next: i => console.log(i),
43 error: err => console.error(err),
44 complete: () => console.log('completed'),
45})
46```
47
48# Installation
49
50```text
51npm install xstream
52```
53
54# Usage
55
56## ES2015 or TypeScript
57
58```js
59import xs from 'xstream'
60```
61
62## CommonJS
63
64```js
65var xs = require('xstream').default
66```
67
68# API
69
70## Factories
71- [`create`](#create)
72- [`createWithMemory`](#createWithMemory)
73- [`never`](#never)
74- [`empty`](#empty)
75- [`throw`](#throw)
76- [`from`](#from)
77- [`of`](#of)
78- [`fromArray`](#fromArray)
79- [`fromPromise`](#fromPromise)
80- [`fromObservable`](#fromObservable)
81- [`periodic`](#periodic)
82- [`merge`](#merge)
83- [`combine`](#combine)
84
85## Methods and Operators
86- [`addListener`](#addListener)
87- [`removeListener`](#removeListener)
88- [`subscribe`](#subscribe)
89- [`map`](#map)
90- [`mapTo`](#mapTo)
91- [`filter`](#filter)
92- [`take`](#take)
93- [`drop`](#drop)
94- [`last`](#last)
95- [`startWith`](#startWith)
96- [`endWhen`](#endWhen)
97- [`fold`](#fold)
98- [`replaceError`](#replaceError)
99- [`flatten`](#flatten)
100- [`compose`](#compose)
101- [`remember`](#remember)
102- [`debug`](#debug)
103- [`imitate`](#imitate)
104- [`shamefullySendNext`](#shamefullySendNext)
105- [`shamefullySendError`](#shamefullySendError)
106- [`shamefullySendComplete`](#shamefullySendComplete)
107- [`setDebugListener`](#setDebugListener)
108
109# Overview
110
111XStream has four fundamental types: Stream, Listener, Producer, and MemoryStream.
112
113## Stream
114
115A Stream is an **event emitter** with multiple Listeners. When an event happens on the
116Stream, it is broadcast to all its Listeners at the same time.
117
118Streams have methods attached to them called *operators*, such as `map`, `filter`, `fold`, `take`, etc. When called, an operator creates and returns another Stream. Once the first Stream broadcasts an event, the event will pass through the operator logic and the output Stream may perhaps broadcast its own event based on the source one.
119
120You can also trigger an event to happen on a Stream with the `shamefullySend*` methods. But you don't want to do that. Really, avoid doing that because it's not the reactive way and you'll be missing the point of this library. Ok?
121
122## Listener
123
124A Listener is an object with one to three functions attached to it: `next`, `error`, and `complete`. There is usually one function for each type of event a Stream may emit but only `next` is always required.
125
126- `next` events are the typical type, they deliver a value.
127- `error` events abort (stop) the execution of the Stream, and happen when something goes wrong in the Stream (or upstream somewhere in the chain of operators)
128- `complete` events signal the peaceful stop of the execution of the Stream.
129
130This is an example of a typical listener:
131
132```js
133var listener = {
134 next: (value) => {
135 console.log('The Stream gave me a value: ', value);
136 },
137 error: (err) => {
138 console.error('The Stream gave me an error: ', err);
139 },
140 complete: () => {
141 console.log('The Stream told me it is done.');
142 },
143}
144```
145
146And this is how you would attach that Listener to a Stream:
147
148<!-- skip-example -->
149```js
150stream.addListener(listener)
151```
152
153And when you think the Listener is done, you can remove it from the Stream:
154
155<!-- skip-example -->
156```js
157stream.removeListener(listener)
158```
159
160## Producer
161
162A Producer is like a machine that produces events to be broadcast on a Stream.
163
164Events from a Stream must come from somewhere, right? That's why we need Producers. They are objects with two functions attached: `start(listener)` and `stop()`. Once you call `start` with a `listener`, the Producer will start generating events and it will send those to the listener. When you call `stop()`, the Producer should quit doing its own thing.
165
166Streams are also Listeners (actually they are "InternalListeners", not Listeners, but that's a detail you can ignore), so you can theoretically give a Stream as the listener in `producer.start(streamAsListener)`. Then, essentially the Producer is now generating events that will be broadcast on the Stream. Nice, huh? Now a bunch of listeners can be attached to the Stream and they can all get those events originally coming from the Producer. That's why `xs.create(producer)` receives a Producer to be the heart of a new Stream. Check this out:
167
168```js
169var producer = {
170 start: function (listener) {
171 this.id = setInterval(() => listener.next('yo'), 1000)
172 },
173
174 stop: function () {
175 clearInterval(this.id)
176 },
177
178 id: 0,
179}
180
181// This fellow delivers a 'yo' next event every 1 second
182var stream = xs.create(producer)
183```
184
185But remember, a Producer has only one listener, but a Stream may have many listeners.
186
187You may wonder "when is `start` and `stop` called", and that's actually a fairly tricky topic, so let's get back to that soon. First let me tell you about MemoryStreams.
188
189## MemoryStream
190
191A MemoryStream is just like a Stream: it has operators, it can have listeners attached, you can shamefully send events to it, blabla. But it has one special property: it has *memory*. It remembers the most recent (but just one) `next` event that it sent to its listeners.
192
193Why is that useful? If a new Listener is added *after* that `next` event was sent, the MemoryStream will get its value stored in memory and will send it to the newly attached Listener.
194
195This is important so MemoryStreams can represent values or pieces of state which are relevant even after some time has passed. You don't want to lose those, you want to keep them and send them to Listeners that arrive late, after the event was originally created.
196
197## How a Stream starts and stops
198
199A Stream controls its Producer according to its number of Listeners, using reference counting with a synchronous `start` and a cancelable asynchronous `stop`. That's how a Stream starts and stops, basically. Usually this part of XStream is not so relevant to remember when building applications, but if you want to understand it for debugging or curiosity, it's explained in plain English below.
200
201When you create a Stream with `xs.create(producer)`, the `start()` function of the Producer is not yet called. The Stream is still "idle". It has the Producer, but the Producer was not turned on.
202
203Once the first Listener is added to the Stream, the number of Listeners attached suddenly changed from `0` to `1`. That's when the Stream calls `start`, because after all there is at least one Listener interested in this Stream.
204
205More Listeners may be added in the future, but they don't affect whether the Producer will continue working or stop. Just the first Listener dictates when the Stream starts.
206
207What matters for stopping the Producer is `stream.removeListener`. When the last Listener leaves (or in other words, when the number of Listeners suddenly changes from `1` to `0`), the Stream schedules `producer.stop()` **to happen on the next event loop**. That is, asynchronously. If, however, a new Listener is added (number goes from `0` to `1`) *before* that scheduled moment, the `producer.stop()` will be cancelled, and the Producer will continue generating events for its Stream normally.
208
209The reason the Producer is not suddenly (synchronously) stopped, is that it is often necessary to swap the single listener of a Stream, but still keep its ongoing execution. For instance:
210
211<!-- skip-example -->
212```js
213var listenerA = {/* ... */}
214var listenerB = {/* ... */}
215
216// number goes from 0 to 1, so the Stream's Producer starts
217stream.addListener(listenerA)
218
219// ...
220
221// number goes from 1 to 0, but then immediately goes back
222// to 1, because listenerB was added
223stream.removeListener(listenerA)
224stream.addListener(listenerB)
225
226// Stream's Producer does not stop, everything continues as before
227```
228
229It's still useful to eventually (asynchronously) stop a Stream's internal Producer, because you don't want useless computation lying around producing gibberish. At least I don't.
230
231# Factories
232
233Factories are functions that create Streams, such as `xs.create()`, `xs.periodic()`, etc.
234
235### <a id="create"></a> `create(producer)`
236
237Creates a new Stream given a Producer.
238
239#### Arguments:
240
241- `producer: Producer` An optional Producer that dictates how to start, generate events, and stop the Stream.
242
243#### Returns: Stream
244
245- - -
246
247### <a id="createWithMemory"></a> `createWithMemory(producer)`
248
249Creates a new MemoryStream given a Producer.
250
251#### Arguments:
252
253- `producer: Producer` An optional Producer that dictates how to start, generate events, and stop the Stream.
254
255#### Returns: MemoryStream
256
257- - -
258
259### <a id="never"></a> `never()`
260
261Creates a Stream that does nothing when started. It never emits any event.
262
263Marble diagram:
264
265```text
266 never
267-----------------------
268```
269
270#### Returns: Stream
271
272- - -
273
274### <a id="empty"></a> `empty()`
275
276Creates a Stream that immediately emits the "complete" notification when
277started, and that's it.
278
279Marble diagram:
280
281```text
282empty
283-|
284```
285
286#### Returns: Stream
287
288- - -
289
290### <a id="throw"></a> `throw(error)`
291
292Creates a Stream that immediately emits an "error" notification with the
293value you passed as the `error` argument when the stream starts, and that's
294it.
295
296Marble diagram:
297
298```text
299throw(X)
300-X
301```
302
303#### Arguments:
304
305- `error` The error event to emit on the created stream.
306
307#### Returns: Stream
308
309- - -
310
311### <a id="from"></a> `from(input)`
312
313Creates a stream from an Array, Promise, or an Observable.
314
315#### Arguments:
316
317- `input: Array|Promise|Observable` The input to make a stream from.
318
319#### Returns: Stream
320
321- - -
322
323### <a id="of"></a> `of(a, b)`
324
325Creates a Stream that immediately emits the arguments that you give to
326*of*, then completes.
327
328Marble diagram:
329
330```text
331of(1,2,3)
332123|
333```
334
335#### Arguments:
336
337- `a` The first value you want to emit as an event on the stream.
338- `b` The second value you want to emit as an event on the stream. One or more of these values may be given as arguments.
339
340#### Returns: Stream
341
342- - -
343
344### <a id="fromArray"></a> `fromArray(array)`
345
346Converts an array to a stream. The returned stream will emit synchronously
347all the items in the array, and then complete.
348
349Marble diagram:
350
351```text
352fromArray([1,2,3])
353123|
354```
355
356#### Arguments:
357
358- `array: Array` The array to be converted as a stream.
359
360#### Returns: Stream
361
362- - -
363
364### <a id="fromPromise"></a> `fromPromise(promise)`
365
366Converts a promise to a stream. The returned stream will emit the resolved
367value of the promise, and then complete. However, if the promise is
368rejected, the stream will emit the corresponding error.
369
370Marble diagram:
371
372```text
373fromPromise( ----42 )
374-----------------42|
375```
376
377#### Arguments:
378
379- `promise: Promise` The promise to be converted as a stream.
380
381#### Returns: Stream
382
383- - -
384
385### <a id="fromObservable"></a> `fromObservable(observable)`
386
387Converts an Observable into a Stream.
388
389#### Arguments:
390
391- `observable: any` The observable to be converted as a stream.
392
393#### Returns: Stream
394
395- - -
396
397### <a id="periodic"></a> `periodic(period)`
398
399Creates a stream that periodically emits incremental numbers, every
400`period` milliseconds.
401
402Marble diagram:
403
404```text
405 periodic(1000)
406---0---1---2---3---4---...
407```
408
409#### Arguments:
410
411- `period: number` The interval in milliseconds to use as a rate of emission.
412
413#### Returns: Stream
414
415- - -
416
417### <a id="merge"></a> `merge(stream1, stream2)`
418
419Blends multiple streams together, emitting events from all of them
420concurrently.
421
422*merge* takes multiple streams as arguments, and creates a stream that
423behaves like each of the argument streams, in parallel.
424
425Marble diagram:
426
427```text
428--1----2-----3--------4---
429----a-----b----c---d------
430 merge
431--1-a--2--b--3-c---d--4---
432```
433
434#### Arguments:
435
436- `stream1: Stream` A stream to merge together with other streams.
437- `stream2: Stream` A stream to merge together with other streams. Two or more streams may be given as arguments.
438
439#### Returns: Stream
440
441- - -
442
443### <a id="combine"></a> `combine(stream1, stream2)`
444
445Combines multiple input streams together to return a stream whose events
446are arrays that collect the latest events from each input stream.
447
448*combine* internally remembers the most recent event from each of the input
449streams. When any of the input streams emits an event, that event together
450with all the other saved events are combined into an array. That array will
451be emitted on the output stream. It's essentially a way of joining together
452the events from multiple streams.
453
454Marble diagram:
455
456```text
457--1----2-----3--------4---
458----a-----b-----c--d------
459 combine
460----1a-2a-2b-3b-3c-3d-4d--
461```
462
463Note: to minimize garbage collection, *combine* uses the same array
464instance for each emission. If you need to compare emissions over time,
465cache the values with `map` first:
466
467```js
468import pairwise from 'xstream/extra/pairwise'
469
470const stream1 = xs.of(1);
471const stream2 = xs.of(2);
472
473xs.combine(stream1, stream2).map(
474 combinedEmissions => ([ ...combinedEmissions ])
475).compose(pairwise)
476```
477
478#### Arguments:
479
480- `stream1: Stream` A stream to combine together with other streams.
481- `stream2: Stream` A stream to combine together with other streams. Multiple streams, not just two, may be given as arguments.
482
483#### Returns: Stream
484
485- - -
486
487
488# Methods and Operators
489
490Methods are functions attached to a Stream instance, like `stream.addListener()`. Operators are also methods, but return a new Stream, leaving the existing Stream unmodified, except for the fact that it has a child Stream attached as Listener.
491
492### <a id="addListener"></a> `addListener(listener)`
493
494Adds a Listener to the Stream.
495
496#### Arguments:
497
498- `listener: Listener`
499
500- - -
501
502### <a id="removeListener"></a> `removeListener(listener)`
503
504Removes a Listener from the Stream, assuming the Listener was added to it.
505
506#### Arguments:
507
508- `listener: Listener\<T>`
509
510- - -
511
512### <a id="subscribe"></a> `subscribe(listener)`
513
514Adds a Listener to the Stream returning a Subscription to remove that
515listener.
516
517#### Arguments:
518
519- `listener: Listener`
520
521#### Returns: Subscription
522
523- - -
524
525### <a id="map"></a> `map(project)`
526
527Transforms each event from the input Stream through a `project` function,
528to get a Stream that emits those transformed events.
529
530Marble diagram:
531
532```text
533--1---3--5-----7------
534 map(i => i * 10)
535--10--30-50----70-----
536```
537
538#### Arguments:
539
540- `project: Function` A function of type `(t: T) => U` that takes event `t` of type `T` from the input Stream and produces an event of type `U`, to
541be emitted on the output Stream.
542
543#### Returns: Stream
544
545- - -
546
547### <a id="mapTo"></a> `mapTo(projectedValue)`
548
549It's like `map`, but transforms each input event to always the same
550constant value on the output Stream.
551
552Marble diagram:
553
554```text
555--1---3--5-----7-----
556 mapTo(10)
557--10--10-10----10----
558```
559
560#### Arguments:
561
562- `projectedValue` A value to emit on the output Stream whenever the input Stream emits any value.
563
564#### Returns: Stream
565
566- - -
567
568### <a id="filter"></a> `filter(passes)`
569
570Only allows events that pass the test given by the `passes` argument.
571
572Each event from the input stream is given to the `passes` function. If the
573function returns `true`, the event is forwarded to the output stream,
574otherwise it is ignored and not forwarded.
575
576Marble diagram:
577
578```text
579--1---2--3-----4-----5---6--7-8--
580 filter(i => i % 2 === 0)
581------2--------4---------6----8--
582```
583
584#### Arguments:
585
586- `passes: Function` A function of type `(t: T) +> boolean` that takes an event from the input stream and checks if it passes, by returning a
587boolean.
588
589#### Returns: Stream
590
591- - -
592
593### <a id="take"></a> `take(amount)`
594
595Lets the first `amount` many events from the input stream pass to the
596output stream, then makes the output stream complete.
597
598Marble diagram:
599
600```text
601--a---b--c----d---e--
602 take(3)
603--a---b--c|
604```
605
606#### Arguments:
607
608- `amount: number` How many events to allow from the input stream before completing the output stream.
609
610#### Returns: Stream
611
612- - -
613
614### <a id="drop"></a> `drop(amount)`
615
616Ignores the first `amount` many events from the input stream, and then
617after that starts forwarding events from the input stream to the output
618stream.
619
620Marble diagram:
621
622```text
623--a---b--c----d---e--
624 drop(3)
625--------------d---e--
626```
627
628#### Arguments:
629
630- `amount: number` How many events to ignore from the input stream before forwarding all events from the input stream to the output stream.
631
632#### Returns: Stream
633
634- - -
635
636### <a id="last"></a> `last()`
637
638When the input stream completes, the output stream will emit the last event
639emitted by the input stream, and then will also complete.
640
641Marble diagram:
642
643```text
644--a---b--c--d----|
645 last()
646-----------------d|
647```
648
649#### Returns: Stream
650
651- - -
652
653### <a id="startWith"></a> `startWith(initial)`
654
655Prepends the given `initial` value to the sequence of events emitted by the
656input stream. The returned stream is a MemoryStream, which means it is
657already `remember()`'d.
658
659Marble diagram:
660
661```text
662---1---2-----3---
663 startWith(0)
6640--1---2-----3---
665```
666
667#### Arguments:
668
669- `initial` The value or event to prepend.
670
671#### Returns: MemoryStream
672
673- - -
674
675### <a id="endWhen"></a> `endWhen(other)`
676
677Uses another stream to determine when to complete the current stream.
678
679When the given `other` stream emits an event or completes, the output
680stream will complete. Before that happens, the output stream will behaves
681like the input stream.
682
683Marble diagram:
684
685```text
686---1---2-----3--4----5----6---
687 endWhen( --------a--b--| )
688---1---2-----3--4--|
689```
690
691#### Arguments:
692
693- `other` Some other stream that is used to know when should the output stream of this operator complete.
694
695#### Returns: Stream
696
697- - -
698
699### <a id="fold"></a> `fold(accumulate, seed)`
700
701"Folds" the stream onto itself.
702
703Combines events from the past throughout
704the entire execution of the input stream, allowing you to accumulate them
705together. It's essentially like `Array.prototype.reduce`. The returned
706stream is a MemoryStream, which means it is already `remember()`'d.
707
708The output stream starts by emitting the `seed` which you give as argument.
709Then, when an event happens on the input stream, it is combined with that
710seed value through the `accumulate` function, and the output value is
711emitted on the output stream. `fold` remembers that output value as `acc`
712("accumulator"), and then when a new input event `t` happens, `acc` will be
713combined with that to produce the new `acc` and so forth.
714
715Marble diagram:
716
717```text
718------1-----1--2----1----1------
719 fold((acc, x) => acc + x, 3)
7203-----4-----5--7----8----9------
721```
722
723#### Arguments:
724
725- `accumulate: Function` A function of type `(acc: R, t: T) => R` that takes the previous accumulated value `acc` and the incoming event from the
726input stream and produces the new accumulated value.
727- `seed` The initial accumulated value, of type `R`.
728
729#### Returns: MemoryStream
730
731- - -
732
733### <a id="replaceError"></a> `replaceError(replace)`
734
735Replaces an error with another stream.
736
737When (and if) an error happens on the input stream, instead of forwarding
738that error to the output stream, *replaceError* will call the `replace`
739function which returns the stream that the output stream will replicate.
740And, in case that new stream also emits an error, `replace` will be called
741again to get another stream to start replicating.
742
743Marble diagram:
744
745```text
746--1---2-----3--4-----X
747 replaceError( () => --10--| )
748--1---2-----3--4--------10--|
749```
750
751#### Arguments:
752
753- `replace: Function` A function of type `(err) => Stream` that takes the error that occurred on the input stream or on the previous replacement
754stream and returns a new stream. The output stream will behave like the
755stream that this function returns.
756
757#### Returns: Stream
758
759- - -
760
761### <a id="flatten"></a> `flatten()`
762
763Flattens a "stream of streams", handling only one nested stream at a time
764(no concurrency).
765
766If the input stream is a stream that emits streams, then this operator will
767return an output stream which is a flat stream: emits regular events. The
768flattening happens without concurrency. It works like this: when the input
769stream emits a nested stream, *flatten* will start imitating that nested
770one. However, as soon as the next nested stream is emitted on the input
771stream, *flatten* will forget the previous nested one it was imitating, and
772will start imitating the new nested one.
773
774Marble diagram:
775
776```text
777--+--------+---------------
778 \ \
779 \ ----1----2---3--
780 --a--b----c----d--------
781 flatten
782-----a--b------1----2---3--
783```
784
785#### Returns: Stream
786
787- - -
788
789### <a id="compose"></a> `compose(operator)`
790
791Passes the input stream to a custom operator, to produce an output stream.
792
793*compose* is a handy way of using an existing function in a chained style.
794Instead of writing `outStream = f(inStream)` you can write
795`outStream = inStream.compose(f)`.
796
797#### Arguments:
798
799- `operator: function` A function that takes a stream as input and returns a stream as well.
800
801#### Returns: Stream
802
803- - -
804
805### <a id="remember"></a> `remember()`
806
807Returns an output stream that behaves like the input stream, but also
808remembers the most recent event that happens on the input stream, so that a
809newly added listener will immediately receive that memorised event.
810
811#### Returns: MemoryStream
812
813- - -
814
815### <a id="debug"></a> `debug(labelOrSpy)`
816
817Returns an output stream that identically behaves like the input stream,
818but also runs a `spy` function fo each event, to help you debug your app.
819
820*debug* takes a `spy` function as argument, and runs that for each event
821happening on the input stream. If you don't provide the `spy` argument,
822then *debug* will just `console.log` each event. This helps you to
823understand the flow of events through some operator chain.
824
825Please note that if the output stream has no listeners, then it will not
826start, which means `spy` will never run because no actual event happens in
827that case.
828
829Marble diagram:
830
831```text
832--1----2-----3-----4--
833 debug
834--1----2-----3-----4--
835```
836
837#### Arguments:
838
839- `labelOrSpy: function` A string to use as the label when printing debug information on the console, or a 'spy' function that takes an event
840as argument, and does not need to return anything.
841
842#### Returns: Stream
843
844- - -
845
846### <a id="imitate"></a> `imitate(target)`
847
848*imitate* changes this current Stream to emit the same events that the
849`other` given Stream does. This method returns nothing.
850
851This method exists to allow one thing: **circular dependency of streams**.
852For instance, let's imagine that for some reason you need to create a
853circular dependency where stream `first$` depends on stream `second$`
854which in turn depends on `first$`:
855
856<!-- skip-example -->
857```js
858import delay from 'xstream/extra/delay'
859
860var first$ = second$.map(x => x * 10).take(3);
861var second$ = first$.map(x => x + 1).startWith(1).compose(delay(100));
862```
863
864However, that is invalid JavaScript, because `second$` is undefined
865on the first line. This is how *imitate* can help solve it:
866
867```js
868import delay from 'xstream/extra/delay'
869
870var secondProxy$ = xs.create();
871var first$ = secondProxy$.map(x => x * 10).take(3);
872var second$ = first$.map(x => x + 1).startWith(1).compose(delay(100));
873secondProxy$.imitate(second$);
874```
875
876We create `secondProxy$` before the others, so it can be used in the
877declaration of `first$`. Then, after both `first$` and `second$` are
878defined, we hook `secondProxy$` with `second$` with `imitate()` to tell
879that they are "the same". `imitate` will not trigger the start of any
880stream, it just binds `secondProxy$` and `second$` together.
881
882The following is an example where `imitate()` is important in Cycle.js
883applications. A parent component contains some child components. A child
884has an action stream which is given to the parent to define its state:
885
886<!-- skip-example -->
887```js
888const childActionProxy$ = xs.create();
889const parent = Parent({...sources, childAction$: childActionProxy$});
890const childAction$ = parent.state$.map(s => s.child.action$).flatten();
891childActionProxy$.imitate(childAction$);
892```
893
894Note, though, that **`imitate()` does not support MemoryStreams**. If we
895would attempt to imitate a MemoryStream in a circular dependency, we would
896either get a race condition (where the symptom would be "nothing happens")
897or an infinite cyclic emission of values. It's useful to think about
898MemoryStreams as cells in a spreadsheet. It doesn't make any sense to
899define a spreadsheet cell `A1` with a formula that depends on `B1` and
900cell `B1` defined with a formula that depends on `A1`.
901
902If you find yourself wanting to use `imitate()` with a
903MemoryStream, you should rework your code around `imitate()` to use a
904Stream instead. Look for the stream in the circular dependency that
905represents an event stream, and that would be a candidate for creating a
906proxy Stream which then imitates the target Stream.
907
908#### Arguments:
909
910- `target: Stream` The other stream to imitate on the current one. Must not be a MemoryStream.
911
912- - -
913
914### <a id="shamefullySendNext"></a> `shamefullySendNext(value)`
915
916Forces the Stream to emit the given value to its listeners.
917
918As the name indicates, if you use this, you are most likely doing something
919The Wrong Way. Please try to understand the reactive way before using this
920method. Use it only when you know what you are doing.
921
922#### Arguments:
923
924- `value` The "next" value you want to broadcast to all listeners of this Stream.
925
926- - -
927
928### <a id="shamefullySendError"></a> `shamefullySendError(error)`
929
930Forces the Stream to emit the given error to its listeners.
931
932As the name indicates, if you use this, you are most likely doing something
933The Wrong Way. Please try to understand the reactive way before using this
934method. Use it only when you know what you are doing.
935
936#### Arguments:
937
938- `error: any` The error you want to broadcast to all the listeners of this Stream.
939
940- - -
941
942### <a id="shamefullySendComplete"></a> `shamefullySendComplete()`
943
944Forces the Stream to emit the "completed" event to its listeners.
945
946As the name indicates, if you use this, you are most likely doing something
947The Wrong Way. Please try to understand the reactive way before using this
948method. Use it only when you know what you are doing.
949
950- - -
951
952### <a id="setDebugListener"></a> `setDebugListener(listener)`
953
954Adds a "debug" listener to the stream. There can only be one debug
955listener, that's why this is 'setDebugListener'. To remove the debug
956listener, just call setDebugListener(null).
957
958A debug listener is like any other listener. The only difference is that a
959debug listener is "stealthy": its presence/absence does not trigger the
960start/stop of the stream (or the producer inside the stream). This is
961useful so you can inspect what is going on without changing the behavior
962of the program. If you have an idle stream and you add a normal listener to
963it, the stream will start executing. But if you set a debug listener on an
964idle stream, it won't start executing (not until the first normal listener
965is added).
966
967As the name indicates, we don't recommend using this method to build app
968logic. In fact, in most cases the debug operator works just fine. Only use
969this one if you know what you're doing.
970
971#### Arguments:
972
973- `listener: Listener\<T>`
974
975- - -
976
977# Extra operators and factories
978
979The operators and factories listed above are the core functions. `xstream` has plenty of extra operators, [documented here](https://github.com/staltz/xstream/blob/master/EXTRA_DOCS.md).
980
981# FAQ
982
983**Q: Why does `imitate()` support a Stream but not a MemoryStream?**
984
985A: MemoryStreams are meant for representing "values over time" (your age), while Streams represent simply events (your birthdays). MemoryStreams are usually initialized with a value, and `imitate()` is meant for creating circular dependencies of streams. If we would attempt to imitate a MemoryStream in a circular dependency, we would either get a race condition (where the symptom would be "nothing happens") or an infinite cyclic emission of values.
986
987If you find yourself wanting to use `imitate()` with a MemoryStream, you should rework your code around `imitate()` to use a Stream instead. Look for the stream in the circular dependency that represents an event stream, and that would be a candidate for creating a MimicStream which then imitates the real event stream.
988
989**Q: What's the difference between xstream and RxJS?**
990
991A: Read this [blog post](http://staltz.com/why-we-built-xstream.html) on the topic. In short:
992
993- xstream Streams are multicast always.
994- RxJS Observables are unicast by default, and opt-in multicast.
995- xstream has few operators *as a feature* (helps against decision paralysis).
996- RxJS has many operators *as a feature* (helps for flexibility and power).
997
998**Q: What is the equivalent of [`withLatestFrom`](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-withLatestFrom) in xstream?**
999
1000A: `withLatestFrom` is implemented as an extra named [`sampleCombine`](https://github.com/staltz/xstream/blob/master/EXTRA_DOCS.md#sampleCombine).
1001
1002-----
1003
1004# Misc.
1005
1006## Acknowledgements
1007
1008*xstream* is built by [staltz](https://github.com/staltz) and [TylorS](https://github.com/tylors).
1009
1010## CHANGELOG
1011
1012Read the [CHANGELOG](https://github.com/staltz/xstream/blob/master/CHANGELOG.md) for release notes of all versions of *xstream*.
1013
1014## License
1015
1016[MIT](https://github.com/staltz/xstream/blob/master/LICENSE)