UNPKG

31 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## Extra factories and operators
110
111To keep the core of xstream small and simple, less frequently-used methods are available under the `xstream/extra` directory, and must be imported separately. See [EXTRA_DOCS](https://github.com/staltz/xstream/blob/master/EXTRA_DOCS.md) for documentation.
112
113# Overview
114
115XStream has four fundamental types: [Stream](#stream), [Listener](#listener), [Producer](#producer), and [MemoryStream](#memorystream).
116
117## Stream
118
119A Stream is an **event emitter** with multiple Listeners. When an event happens on the
120Stream, it is broadcast to all its Listeners at the same time.
121
122Streams 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.
123
124You 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?
125
126## Listener
127
128A 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.
129
130- `next` events are the typical type, they deliver a value.
131- `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)
132- `complete` events signal the peaceful stop of the execution of the Stream.
133
134This is an example of a typical listener:
135
136```js
137var listener = {
138 next: (value) => {
139 console.log('The Stream gave me a value: ', value);
140 },
141 error: (err) => {
142 console.error('The Stream gave me an error: ', err);
143 },
144 complete: () => {
145 console.log('The Stream told me it is done.');
146 },
147}
148```
149
150And this is how you would attach that Listener to a Stream:
151
152<!-- skip-example -->
153```js
154stream.addListener(listener)
155```
156
157And when you think the Listener is done, you can remove it from the Stream:
158
159<!-- skip-example -->
160```js
161stream.removeListener(listener)
162```
163
164## Producer
165
166A Producer is like a machine that produces events to be broadcast on a Stream.
167
168Events 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.
169
170Streams 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:
171
172```js
173var producer = {
174 start: function (listener) {
175 this.id = setInterval(() => listener.next('yo'), 1000)
176 },
177
178 stop: function () {
179 clearInterval(this.id)
180 },
181
182 id: 0,
183}
184
185// This fellow delivers a 'yo' next event every 1 second
186var stream = xs.create(producer)
187```
188
189But remember, a Producer has only one listener, but a Stream may have many listeners.
190
191You 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.
192
193## MemoryStream
194
195A 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.
196
197Why 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.
198
199This 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.
200
201## How a Stream starts and stops
202
203A 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.
204
205When 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.
206
207Once 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.
208
209More 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.
210
211What 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.
212
213The 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:
214
215<!-- skip-example -->
216```js
217var listenerA = {/* ... */}
218var listenerB = {/* ... */}
219
220// number goes from 0 to 1, so the Stream's Producer starts
221stream.addListener(listenerA)
222
223// ...
224
225// number goes from 1 to 0, but then immediately goes back
226// to 1, because listenerB was added
227stream.removeListener(listenerA)
228stream.addListener(listenerB)
229
230// Stream's Producer does not stop, everything continues as before
231```
232
233It'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.
234
235# Factories
236
237Factories are functions that create Streams, such as `xs.create()`, `xs.periodic()`, etc.
238
239### <a id="create"></a> `create(producer)`
240
241Creates a new Stream given a Producer.
242
243#### Arguments:
244
245- `producer: Producer` An optional Producer that dictates how to start, generate events, and stop the Stream.
246
247#### Returns: Stream
248
249- - -
250
251### <a id="createWithMemory"></a> `createWithMemory(producer)`
252
253Creates a new MemoryStream given a Producer.
254
255#### Arguments:
256
257- `producer: Producer` An optional Producer that dictates how to start, generate events, and stop the Stream.
258
259#### Returns: MemoryStream
260
261- - -
262
263### <a id="never"></a> `never()`
264
265Creates a Stream that does nothing when started. It never emits any event.
266
267Marble diagram:
268
269```text
270 never
271-----------------------
272```
273
274#### Returns: Stream
275
276- - -
277
278### <a id="empty"></a> `empty()`
279
280Creates a Stream that immediately emits the "complete" notification when
281started, and that's it.
282
283Marble diagram:
284
285```text
286empty
287-|
288```
289
290#### Returns: Stream
291
292- - -
293
294### <a id="throw"></a> `throw(error)`
295
296Creates a Stream that immediately emits an "error" notification with the
297value you passed as the `error` argument when the stream starts, and that's
298it.
299
300Marble diagram:
301
302```text
303throw(X)
304-X
305```
306
307#### Arguments:
308
309- `error` The error event to emit on the created stream.
310
311#### Returns: Stream
312
313- - -
314
315### <a id="from"></a> `from(input)`
316
317Creates a stream from an Array, Promise, or an Observable.
318
319#### Arguments:
320
321- `input: Array|PromiseLike|Observable` The input to make a stream from.
322
323#### Returns: Stream
324
325- - -
326
327### <a id="of"></a> `of(a, b)`
328
329Creates a Stream that immediately emits the arguments that you give to
330*of*, then completes.
331
332Marble diagram:
333
334```text
335of(1,2,3)
336123|
337```
338
339#### Arguments:
340
341- `a` The first value you want to emit as an event on the stream.
342- `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.
343
344#### Returns: Stream
345
346- - -
347
348### <a id="fromArray"></a> `fromArray(array)`
349
350Converts an array to a stream. The returned stream will emit synchronously
351all the items in the array, and then complete.
352
353Marble diagram:
354
355```text
356fromArray([1,2,3])
357123|
358```
359
360#### Arguments:
361
362- `array: Array` The array to be converted as a stream.
363
364#### Returns: Stream
365
366- - -
367
368### <a id="fromPromise"></a> `fromPromise(promise)`
369
370Converts a promise to a stream. The returned stream will emit the resolved
371value of the promise, and then complete. However, if the promise is
372rejected, the stream will emit the corresponding error.
373
374Marble diagram:
375
376```text
377fromPromise( ----42 )
378-----------------42|
379```
380
381#### Arguments:
382
383- `promise: PromiseLike` The promise to be converted as a stream.
384
385#### Returns: Stream
386
387- - -
388
389### <a id="fromObservable"></a> `fromObservable(observable)`
390
391Converts an Observable into a Stream.
392
393#### Arguments:
394
395- `observable: any` The observable to be converted as a stream.
396
397#### Returns: Stream
398
399- - -
400
401### <a id="periodic"></a> `periodic(period)`
402
403Creates a stream that periodically emits incremental numbers, every
404`period` milliseconds.
405
406Marble diagram:
407
408```text
409 periodic(1000)
410---0---1---2---3---4---...
411```
412
413#### Arguments:
414
415- `period: number` The interval in milliseconds to use as a rate of emission.
416
417#### Returns: Stream
418
419- - -
420
421### <a id="merge"></a> `merge(stream1, stream2)`
422
423Blends multiple streams together, emitting events from all of them
424concurrently.
425
426*merge* takes multiple streams as arguments, and creates a stream that
427behaves like each of the argument streams, in parallel.
428
429Marble diagram:
430
431```text
432--1----2-----3--------4---
433----a-----b----c---d------
434 merge
435--1-a--2--b--3-c---d--4---
436```
437
438#### Arguments:
439
440- `stream1: Stream` A stream to merge together with other streams.
441- `stream2: Stream` A stream to merge together with other streams. Two or more streams may be given as arguments.
442
443#### Returns: Stream
444
445- - -
446
447### <a id="combine"></a> `combine(stream1, stream2)`
448
449Combines multiple input streams together to return a stream whose events
450are arrays that collect the latest events from each input stream.
451
452*combine* internally remembers the most recent event from each of the input
453streams. When any of the input streams emits an event, that event together
454with all the other saved events are combined into an array. That array will
455be emitted on the output stream. It's essentially a way of joining together
456the events from multiple streams.
457
458Marble diagram:
459
460```text
461--1----2-----3--------4---
462----a-----b-----c--d------
463 combine
464----1a-2a-2b-3b-3c-3d-4d--
465```
466
467Note: to minimize garbage collection, *combine* uses the same array
468instance for each emission. If you need to compare emissions over time,
469cache the values with `map` first:
470
471```js
472import pairwise from 'xstream/extra/pairwise'
473
474const stream1 = xs.of(1);
475const stream2 = xs.of(2);
476
477xs.combine(stream1, stream2).map(
478 combinedEmissions => ([ ...combinedEmissions ])
479).compose(pairwise)
480```
481
482#### Arguments:
483
484- `stream1: Stream` A stream to combine together with other streams.
485- `stream2: Stream` A stream to combine together with other streams. Multiple streams, not just two, may be given as arguments.
486
487#### Returns: Stream
488
489- - -
490
491
492# Methods and Operators
493
494Methods 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.
495
496### <a id="addListener"></a> `addListener(listener)`
497
498Adds a Listener to the Stream.
499
500#### Arguments:
501
502- `listener: Listener`
503
504- - -
505
506### <a id="removeListener"></a> `removeListener(listener)`
507
508Removes a Listener from the Stream, assuming the Listener was added to it.
509
510#### Arguments:
511
512- `listener: Listener\<T>`
513
514- - -
515
516### <a id="subscribe"></a> `subscribe(listener)`
517
518Adds a Listener to the Stream returning a Subscription to remove that
519listener.
520
521#### Arguments:
522
523- `listener: Listener`
524
525#### Returns: Subscription
526
527- - -
528
529### <a id="map"></a> `map(project)`
530
531Transforms each event from the input Stream through a `project` function,
532to get a Stream that emits those transformed events.
533
534Marble diagram:
535
536```text
537--1---3--5-----7------
538 map(i => i * 10)
539--10--30-50----70-----
540```
541
542#### Arguments:
543
544- `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
545be emitted on the output Stream.
546
547#### Returns: Stream
548
549- - -
550
551### <a id="mapTo"></a> `mapTo(projectedValue)`
552
553It's like `map`, but transforms each input event to always the same
554constant value on the output Stream.
555
556Marble diagram:
557
558```text
559--1---3--5-----7-----
560 mapTo(10)
561--10--10-10----10----
562```
563
564#### Arguments:
565
566- `projectedValue` A value to emit on the output Stream whenever the input Stream emits any value.
567
568#### Returns: Stream
569
570- - -
571
572### <a id="filter"></a> `filter(passes)`
573
574Only allows events that pass the test given by the `passes` argument.
575
576Each event from the input stream is given to the `passes` function. If the
577function returns `true`, the event is forwarded to the output stream,
578otherwise it is ignored and not forwarded.
579
580Marble diagram:
581
582```text
583--1---2--3-----4-----5---6--7-8--
584 filter(i => i % 2 === 0)
585------2--------4---------6----8--
586```
587
588#### Arguments:
589
590- `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
591boolean.
592
593#### Returns: Stream
594
595- - -
596
597### <a id="take"></a> `take(amount)`
598
599Lets the first `amount` many events from the input stream pass to the
600output stream, then makes the output stream complete.
601
602Marble diagram:
603
604```text
605--a---b--c----d---e--
606 take(3)
607--a---b--c|
608```
609
610#### Arguments:
611
612- `amount: number` How many events to allow from the input stream before completing the output stream.
613
614#### Returns: Stream
615
616- - -
617
618### <a id="drop"></a> `drop(amount)`
619
620Ignores the first `amount` many events from the input stream, and then
621after that starts forwarding events from the input stream to the output
622stream.
623
624Marble diagram:
625
626```text
627--a---b--c----d---e--
628 drop(3)
629--------------d---e--
630```
631
632#### Arguments:
633
634- `amount: number` How many events to ignore from the input stream before forwarding all events from the input stream to the output stream.
635
636#### Returns: Stream
637
638- - -
639
640### <a id="last"></a> `last()`
641
642When the input stream completes, the output stream will emit the last event
643emitted by the input stream, and then will also complete.
644
645Marble diagram:
646
647```text
648--a---b--c--d----|
649 last()
650-----------------d|
651```
652
653#### Returns: Stream
654
655- - -
656
657### <a id="startWith"></a> `startWith(initial)`
658
659Prepends the given `initial` value to the sequence of events emitted by the
660input stream. The returned stream is a MemoryStream, which means it is
661already `remember()`'d.
662
663Marble diagram:
664
665```text
666---1---2-----3---
667 startWith(0)
6680--1---2-----3---
669```
670
671#### Arguments:
672
673- `initial` The value or event to prepend.
674
675#### Returns: MemoryStream
676
677- - -
678
679### <a id="endWhen"></a> `endWhen(other)`
680
681Uses another stream to determine when to complete the current stream.
682
683When the given `other` stream emits an event or completes, the output
684stream will complete. Before that happens, the output stream will behaves
685like the input stream.
686
687Marble diagram:
688
689```text
690---1---2-----3--4----5----6---
691 endWhen( --------a--b--| )
692---1---2-----3--4--|
693```
694
695#### Arguments:
696
697- `other` Some other stream that is used to know when should the output stream of this operator complete.
698
699#### Returns: Stream
700
701- - -
702
703### <a id="fold"></a> `fold(accumulate, seed)`
704
705"Folds" the stream onto itself.
706
707Combines events from the past throughout
708the entire execution of the input stream, allowing you to accumulate them
709together. It's essentially like `Array.prototype.reduce`. The returned
710stream is a MemoryStream, which means it is already `remember()`'d.
711
712The output stream starts by emitting the `seed` which you give as argument.
713Then, when an event happens on the input stream, it is combined with that
714seed value through the `accumulate` function, and the output value is
715emitted on the output stream. `fold` remembers that output value as `acc`
716("accumulator"), and then when a new input event `t` happens, `acc` will be
717combined with that to produce the new `acc` and so forth.
718
719Marble diagram:
720
721```text
722------1-----1--2----1----1------
723 fold((acc, x) => acc + x, 3)
7243-----4-----5--7----8----9------
725```
726
727#### Arguments:
728
729- `accumulate: Function` A function of type `(acc: R, t: T) => R` that takes the previous accumulated value `acc` and the incoming event from the
730input stream and produces the new accumulated value.
731- `seed` The initial accumulated value, of type `R`.
732
733#### Returns: MemoryStream
734
735- - -
736
737### <a id="replaceError"></a> `replaceError(replace)`
738
739Replaces an error with another stream.
740
741When (and if) an error happens on the input stream, instead of forwarding
742that error to the output stream, *replaceError* will call the `replace`
743function which returns the stream that the output stream will replicate.
744And, in case that new stream also emits an error, `replace` will be called
745again to get another stream to start replicating.
746
747Marble diagram:
748
749```text
750--1---2-----3--4-----X
751 replaceError( () => --10--| )
752--1---2-----3--4--------10--|
753```
754
755#### Arguments:
756
757- `replace: Function` A function of type `(err) => Stream` that takes the error that occurred on the input stream or on the previous replacement
758stream and returns a new stream. The output stream will behave like the
759stream that this function returns.
760
761#### Returns: Stream
762
763- - -
764
765### <a id="flatten"></a> `flatten()`
766
767Flattens a "stream of streams", handling only one nested stream at a time
768(no concurrency).
769
770If the input stream is a stream that emits streams, then this operator will
771return an output stream which is a flat stream: emits regular events. The
772flattening happens without concurrency. It works like this: when the input
773stream emits a nested stream, *flatten* will start imitating that nested
774one. However, as soon as the next nested stream is emitted on the input
775stream, *flatten* will forget the previous nested one it was imitating, and
776will start imitating the new nested one.
777
778Marble diagram:
779
780```text
781--+--------+---------------
782 \ \
783 \ ----1----2---3--
784 --a--b----c----d--------
785 flatten
786-----a--b------1----2---3--
787```
788
789#### Returns: Stream
790
791- - -
792
793### <a id="compose"></a> `compose(operator)`
794
795Passes the input stream to a custom operator, to produce an output stream.
796
797*compose* is a handy way of using an existing function in a chained style.
798Instead of writing `outStream = f(inStream)` you can write
799`outStream = inStream.compose(f)`.
800
801#### Arguments:
802
803- `operator: function` A function that takes a stream as input and returns a stream as well.
804
805#### Returns: Stream
806
807- - -
808
809### <a id="remember"></a> `remember()`
810
811Returns an output stream that behaves like the input stream, but also
812remembers the most recent event that happens on the input stream, so that a
813newly added listener will immediately receive that memorised event.
814
815#### Returns: MemoryStream
816
817- - -
818
819### <a id="debug"></a> `debug(labelOrSpy)`
820
821Returns an output stream that identically behaves like the input stream,
822but also runs a `spy` function for each event, to help you debug your app.
823
824*debug* takes a `spy` function as argument, and runs that for each event
825happening on the input stream. If you don't provide the `spy` argument,
826then *debug* will just `console.log` each event. This helps you to
827understand the flow of events through some operator chain.
828
829Please note that if the output stream has no listeners, then it will not
830start, which means `spy` will never run because no actual event happens in
831that case.
832
833Marble diagram:
834
835```text
836--1----2-----3-----4--
837 debug
838--1----2-----3-----4--
839```
840
841#### Arguments:
842
843- `labelOrSpy: function` A string to use as the label when printing debug information on the console, or a 'spy' function that takes an event
844as argument, and does not need to return anything.
845
846#### Returns: Stream
847
848- - -
849
850### <a id="imitate"></a> `imitate(target)`
851
852*imitate* changes this current Stream to emit the same events that the
853`other` given Stream does. This method returns nothing.
854
855This method exists to allow one thing: **circular dependency of streams**.
856For instance, let's imagine that for some reason you need to create a
857circular dependency where stream `first$` depends on stream `second$`
858which in turn depends on `first$`:
859
860<!-- skip-example -->
861```js
862import delay from 'xstream/extra/delay'
863
864var first$ = second$.map(x => x * 10).take(3);
865var second$ = first$.map(x => x + 1).startWith(1).compose(delay(100));
866```
867
868However, that is invalid JavaScript, because `second$` is undefined
869on the first line. This is how *imitate* can help solve it:
870
871```js
872import delay from 'xstream/extra/delay'
873
874var secondProxy$ = xs.create();
875var first$ = secondProxy$.map(x => x * 10).take(3);
876var second$ = first$.map(x => x + 1).startWith(1).compose(delay(100));
877secondProxy$.imitate(second$);
878```
879
880We create `secondProxy$` before the others, so it can be used in the
881declaration of `first$`. Then, after both `first$` and `second$` are
882defined, we hook `secondProxy$` with `second$` with `imitate()` to tell
883that they are "the same". `imitate` will not trigger the start of any
884stream, it just binds `secondProxy$` and `second$` together.
885
886The following is an example where `imitate()` is important in Cycle.js
887applications. A parent component contains some child components. A child
888has an action stream which is given to the parent to define its state:
889
890<!-- skip-example -->
891```js
892const childActionProxy$ = xs.create();
893const parent = Parent({...sources, childAction$: childActionProxy$});
894const childAction$ = parent.state$.map(s => s.child.action$).flatten();
895childActionProxy$.imitate(childAction$);
896```
897
898Note, though, that **`imitate()` does not support MemoryStreams**. If we
899would attempt to imitate a MemoryStream in a circular dependency, we would
900either get a race condition (where the symptom would be "nothing happens")
901or an infinite cyclic emission of values. It's useful to think about
902MemoryStreams as cells in a spreadsheet. It doesn't make any sense to
903define a spreadsheet cell `A1` with a formula that depends on `B1` and
904cell `B1` defined with a formula that depends on `A1`.
905
906If you find yourself wanting to use `imitate()` with a
907MemoryStream, you should rework your code around `imitate()` to use a
908Stream instead. Look for the stream in the circular dependency that
909represents an event stream, and that would be a candidate for creating a
910proxy Stream which then imitates the target Stream.
911
912#### Arguments:
913
914- `target: Stream` The other stream to imitate on the current one. Must not be a MemoryStream.
915
916- - -
917
918### <a id="shamefullySendNext"></a> `shamefullySendNext(value)`
919
920Forces the Stream to emit the given value to its listeners.
921
922As the name indicates, if you use this, you are most likely doing something
923The Wrong Way. Please try to understand the reactive way before using this
924method. Use it only when you know what you are doing.
925
926#### Arguments:
927
928- `value` The "next" value you want to broadcast to all listeners of this Stream.
929
930- - -
931
932### <a id="shamefullySendError"></a> `shamefullySendError(error)`
933
934Forces the Stream to emit the given error to its listeners.
935
936As the name indicates, if you use this, you are most likely doing something
937The Wrong Way. Please try to understand the reactive way before using this
938method. Use it only when you know what you are doing.
939
940#### Arguments:
941
942- `error: any` The error you want to broadcast to all the listeners of this Stream.
943
944- - -
945
946### <a id="shamefullySendComplete"></a> `shamefullySendComplete()`
947
948Forces the Stream to emit the "completed" event to its listeners.
949
950As the name indicates, if you use this, you are most likely doing something
951The Wrong Way. Please try to understand the reactive way before using this
952method. Use it only when you know what you are doing.
953
954- - -
955
956### <a id="setDebugListener"></a> `setDebugListener(listener)`
957
958Adds a "debug" listener to the stream. There can only be one debug
959listener, that's why this is 'setDebugListener'. To remove the debug
960listener, just call setDebugListener(null).
961
962A debug listener is like any other listener. The only difference is that a
963debug listener is "stealthy": its presence/absence does not trigger the
964start/stop of the stream (or the producer inside the stream). This is
965useful so you can inspect what is going on without changing the behavior
966of the program. If you have an idle stream and you add a normal listener to
967it, the stream will start executing. But if you set a debug listener on an
968idle stream, it won't start executing (not until the first normal listener
969is added).
970
971As the name indicates, we don't recommend using this method to build app
972logic. In fact, in most cases the debug operator works just fine. Only use
973this one if you know what you're doing.
974
975#### Arguments:
976
977- `listener: Listener\<T>`
978
979- - -
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)