├── dummy.js ├── bufferWithCount.md ├── history.md └── README.md /dummy.js: -------------------------------------------------------------------------------- 1 | // Tells GitHub this repo is about JavaScript 2 | -------------------------------------------------------------------------------- /bufferWithCount.md: -------------------------------------------------------------------------------- 1 | ### Buffer every N events and emit as single event 2 | 3 | ```js 4 | import Most from "most"; 5 | import {add, append, curry, takeLast} from "ramda"; 6 | 7 | // Number -> Stream a -> Stream [a] 8 | let buffer = curry((n, s$) => { 9 | return s$ 10 | .loop((memo, item) => { 11 | let value = takeLast(n, append(item, memo)); 12 | let seed = value.length == n ? [] : value; 13 | return {seed, value}; 14 | }, []) 15 | .filter(x => x.length == n) 16 | }); 17 | 18 | let s$ = Most 19 | .periodic(100, 1) 20 | .scan(add, 0); // 0--1--2--... 21 | 22 | buffer(3, s$) // [0, 1, 2]--[3, 4, 5]--... 23 | .observe(console.log); 24 | ``` 25 | -------------------------------------------------------------------------------- /history.md: -------------------------------------------------------------------------------- 1 | ### Track history for N events 2 | 3 | #### RxJS 4 | 5 | ```js 6 | let {append, drop, repeat} = require("ramda") 7 | 8 | let appendSliding = curry((n, x, xs) => { 9 | let ys = append(x, xs) 10 | if (ys.length > n) { 11 | return drop(ys.length - n, ys) 12 | } else { 13 | return ys 14 | } 15 | }) 16 | 17 | let history = function (n) { 18 | if (n <= 0) { 19 | throw Error("n must be an unsigned integer, got "+ String(n)) 20 | } 21 | let put = appendSliding(n) 22 | return this.scan((stateHistory, newState) => { 23 | return put(newState, stateHistory) 24 | }, repeat(null, n)) 25 | } 26 | 27 | // Usage 28 | statefulStream 29 | ::history(3) 30 | ``` 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Reactive polyglot 2 | 3 | **`R.`** [(Ramda)](http://ramdajs.com/0.19.1/index.html) stands for standard functional toolkit. 4 | 5 | ### Comparison notes 6 | 7 | Operator counterparts aren't and can't be fully equivalent.
8 | "Kinda the same" – is the current definition. 9 | 10 | The following projects, were created with different goals and tradeoffs in mind, so every comparison 11 | and analogy is subjective and can be argued. The presence of some operator is not necessary good, as 12 | well as the abscence is not necessary bad. 13 | 14 | Note, that primitives differ for each library. In descriptions, we broadly refer to all the "observable 15 | primitives" as **streams***, though, technically speaking, some of them are rather stream-like entities. 16 | 17 | To find something, search for a term you know. 18 | 19 | ## API 20 | 21 | ### Create 22 | 23 | #### Create an empty stream 24 | 25 | * KefirJS: [`never`](http://kefirjs.github.io/kefir/#never) 26 | * MostJS: [`empty`](https://github.com/cujojs/most/blob/master/docs/api.md#mostempty) 27 | * RxJS: [`of`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/of.md) 28 | * XStream: [`empty`](https://github.com/staltz/xstream#of) 29 | 30 | #### Create a stream from a single value 31 | 32 | * KefirJS: [`constant`](http://kefirjs.github.io/kefir/#constant) 33 | * MostJS: [`of`](https://github.com/cujojs/most/blob/master/docs/api.md#mostjust), [`just`](https://github.com/cujojs/most/blob/master/docs/api.md#mostjust) 34 | * RxJS: [`of`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/of.md), [`just`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/return.md) 35 | * XStream: [`of`](https://github.com/staltz/xstream#of) 36 | 37 | #### Create a stream from an array 38 | 39 | * KefirJS: [`sequentially`](http://kefirjs.github.io/kefir/#sequentially) 40 | * MostJS: [`from`](https://github.com/cujojs/most/blob/master/docs/api.md#mostfrom) 41 | * RxJS: [`from`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/from.md), [`of`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/of.md) 42 | * XStream: [`from`](https://github.com/staltz/xstream#from), [`fromArray`](https://github.com/staltz/xstream#fromArray) 43 | 44 | #### Create a stream from a promise 45 | 46 | * KefirJS: [`fromPromise`](http://kefirjs.github.io/kefir/#from-promise) 47 | * MostJS: [`fromPromise`](https://github.com/cujojs/most/blob/master/docs/api.md#mostfrompromise) 48 | * RxJS: [`fromPromise`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/frompromise.md) 49 | * XStream: [`fromPromise`](https://github.com/staltz/xstream#fromPromise) 50 | 51 | #### Create a stream from an event 52 | 53 | * KefirJS: [`fromEvents`](http://kefirjs.github.io/kefir/#from-event) 54 | * MostJS: [`fromEvent`](https://github.com/cujojs/most/blob/master/docs/api.md#mostfromevent) 55 | * RxJS: [`fromEvent`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/fromevent.md) 56 | * XStream: [`fromEvent`](https://github.com/staltz/xstream/blob/master/EXTRA_DOCS.md#fromEvent) 57 | 58 | #### Create a stream from a callback 59 | 60 | * KefirJS: [`stream`](http://kefirjs.github.io/kefir/#stream), [`fromCallback`](http://kefirjs.github.io/kefir/#from-callback), [`fromNodeCallback`](http://kefirjs.github.io/kefir/#from-node-callback), [`fromPoll`](http://kefirjs.github.io/kefir/#from-poll) 61 | * MostJS: `new Stream` 62 | * RxJS: `new Observable`, `bindCallback`, `bindNodeCallback` 63 | * XStream: `? (make a promise first)` 64 | 65 | #### Prepend a stream with a value 66 | 67 | * KefirJS: [`merge`](http://kefirjs.github.io/kefir/#merge) `+` [`constant`](http://kefirjs.github.io/kefir/#constant) 68 | * MostJS: `startWith` 69 | * RxJS: [`startWith`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/startwith.md) 70 | * XStream: `startWith` 71 | 72 | ### Transform (data events) 73 | 74 | #### Map value one-to-one 75 | 76 | * KefirJS: [`map`](http://kefirjs.github.io/kefir/#map) 77 | * MostJS: `map`, `constant` 78 | * RxJS: [`map`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/select.md), `mapTo` 79 | * XStream: `map` 80 | 81 | #### Filter value by a predicate 82 | 83 | * KefirJS: [`filter`](http://kefirjs.github.io/kefir/#filter) 84 | * MostJS: `filter` 85 | * RxJS: [`filter`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/where.md) 86 | * XStream: `filter` 87 | 88 | #### Skip N initial values 89 | 90 | * KefirJS: [`skip`](http://kefirjs.github.io/kefir/#skip) 91 | * MostJS: `skip` 92 | * RxJS: [`skip`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/skip.md) 93 | * XStream: `drop` 94 | 95 | #### Take N initial values 96 | 97 | * KefirJS: [`take`](http://kefirjs.github.io/kefir/#take) 98 | * MostJS: `take` 99 | * RxJS: [`take`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/take.md) 100 | * XStream: `take` 101 | 102 | #### Make a value from an accumulator and a next value 103 | 104 | * KefirJS: [`scan`](http://kefirjs.github.io/kefir/#scan) 105 | * MostJS: `scan` 106 | * RxJS: [`scan`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/scan.md) 107 | * XStream: `fold` 108 | 109 | ### Combine 110 | 111 | #### Merge multiple streams together 112 | 113 | * KefirJS: [`merge`](http://kefirjs.github.io/kefir/#merge) 114 | * MostJS: `merge` 115 | * RxJS: [`merge`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/merge.md) 116 | * XStream: `merge` 117 | 118 | Pay attention that Kefir's `merge` accepts arrays while others are variadic. 119 | 120 | #### Combine multiple streams together 121 | 122 | * KefirJS: [`combine`](http://kefirjs.github.io/kefir/#combine) 123 | * MostJS: `combine` 124 | * RxJS: [`combineLatest`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/combinelatest.md) 125 | * XStream: `combine` 126 | 127 | #### Sample a stream by another stream 128 | 129 | * KefirJS: [`combine`](http://kefirjs.github.io/kefir/#combine), [`sampledBy`](http://kefirjs.github.io/kefir/#obs-sampled-by) 130 | * MostJS: `sample`, `sampleWith` 131 | * RxJS: [`sample`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/sample.md), [`withLatestFrom`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/withlatestfrom.md) 132 | * XStream: `sampleCombine` 133 | 134 | #### Chain streams sequentially 135 | 136 | * KefirJS: [`flatMapConcat`](http://kefirjs.github.io/kefir/#flat-map-concat) 137 | * MostJS: [`concatMap`](https://github.com/cujojs/most/blob/master/docs/api.md#concatmap) 138 | * RxJS: [`concatMap`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/concatmap.md) 139 | * XStream: `map + flattenSequentially` 140 | 141 | --- 142 | 143 | ### Create 144 | 145 | Create stream from non-stream values. 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 |
KefirJSMostJSRxJSXStream
intervalperiodicinterval + mapperiodic
repeatof + R.rangerepeatof + R.range
?iterategenerate?
?generategenerate?
179 | 180 | ### Mapper 181 | 182 | Modify events one to one. 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 |
KefirJSMostJSRxJSXStream
delaydelaydelaycombine(delay(500))
– (map)timestamptimestamp– (map)
204 | 205 | ### Transforms 206 | 207 | Modify events * to *. 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 |
MostJSRxJSXStream
chain / flatMapflatMapmap + flattenConcurrently
map + switchswitchMap / flatMapLatestmap + flatten
joinmergeAllflatten
loopscan + mapfold + map
– (custom)bufferWithCount?
241 | 242 | ### Filters 243 | 244 | Skip events by predicate or signal. 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 |
MostJSRxJSXStream
skipRepeatsdistinctUntilChangeddropRepeats
skipRepeatsWith– (scan)dropRepeats
sliceskip + takedrop + take
skipWhileskipWhilefold + filter + map
takeWhiletakeWhilefilter + endWhen
since / skipUntilskipUntilfold + filter + map
until / takeUntiltakeUntilfilter + endWhen
duringwindow + take(1)?
293 | 294 | ### Combinators 295 | 296 | Combine multiple streams into single. 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 |
MostJSRxJSXStream
zipzip?
concatconcatconcat
apcombineLatest?
320 | 321 | ### Side effects 322 | 323 | Produce side effect for every event. 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 |
MostJSRxJSXStream
tapdo / tapdebug
337 | 338 | ### Ending 339 | 340 | Operators which target **end** event somehow. 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 |
MostJSRxJSXStream
emptyemptyempty
nevernevernever
continueWith?concat
364 | 365 | ### Concurrency 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 |
MostJSRxJS
– (custom)amb / race
377 | 378 | ### History 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 |
MostJSRxJS
– (custom)
389 | 390 | ### Design diffs 391 | 392 | #### RxJS 393 | 394 | 1. Three primitives: `Observer`, `Observable`, `Subject`. 395 | 2. Observables end on error. 396 | 3. Provides API to handle errors. 397 | 3. Does not provide API to handle ending. 398 | 399 | #### KefirJS 400 | 401 | 1. Two primitives: `Stream` and `Property` (like XStream). 402 | 2. Observables does not end on error (by default). 403 | 3. Provides API to handle errors. 404 | 4. Provides API to handle ending. 405 | 406 | #### MostJS 407 | 408 | 1. One primitive: `Stream` (+ community-driven). 409 | 2. Separate packages for [subject-like](https://github.com/TylorS/most-subject) and [property-like](https://github.com/mostjs/hold) primitives. 410 | 3. Provides API to handle errors. 411 | 4. Provides API to handle ending. 412 | 413 | #### XStream 414 | 415 | 1. Two primitives: `Stream` and `MemoryStream` (like KefirJS). 416 | 2. Always multicast. A Stream is like an RxJS Subject. 417 | 3. Streams end on error. 418 | 419 | #### Common 420 | 421 | RxJS does not emit initial `scan` value as event (use `startWith` for that). 422 | 423 | ```js 424 | Rx.Observable.interval(100).map(x => 1) 425 | .scan(add, 0); 426 | .subscribe(console.log); // 1--2--3--... 427 | 428 | Most.periodic(100, 1) 429 | .scan(add, 0); 430 | .observe(console.log); // 0--1--2--3--... 431 | ``` 432 | 433 | ### Found docs / API quirks 434 | 435 | #### MostJS 436 | 437 | `startWith` vs `sampleWith` vs `continueWith` + `recoverWith` vs `skipRepeatsWith`
438 | (val vs none vs func vs stream) 439 | 440 | `tap` is listed in "Transform" section. 441 | 442 | #### RxJS 443 | 444 | `startWith` is listed in "Combine" section. 445 | 446 | `mergeAll` is listed in "Combine" section. 447 | 448 | `distinct` is not listed in "Filtering" section. 449 | 450 | `takeUntil` is not listed in "Filtering" section. 451 | 452 | `just` / `return` should be deprecated in favor of `of`. 453 | 454 | `fromArray` should be deprecated in favor of `from`. 455 | 456 | ### Links 457 | 458 | [bacon-vs-kefir](https://github.com/rpominov/kefir/blob/master/bacon-vs-kefir-api.md) – BaconJS vs KefirJS API comparison 459 | 460 | [dataflows](https://github.com/ivan-kleshnin/dataflows) – web arch. dataflow comparison 461 | 462 | [stream-conversions](https://github.com/TylorS/stream-conversions) – tool for cross-library stream conversions 463 | 464 | ### Additional Read 465 | 466 | https://github.com/cujojs/most/issues/171 467 | 468 | https://twitter.com/rpominov/status/689566111734599683 469 | 470 | https://github.com/zenparsing/es-observable/issues/66 471 | 472 | # Reactive polyglot 473 | 474 | **`R.`** [(Ramda)](http://ramdajs.com/0.19.1/index.html) stands for standard functional toolkit. 475 | 476 | ### Comparison notes 477 | 478 | Operator counterparts aren't and can't be fully equivalent.
479 | "Kinda the same" – is the current definition. 480 | 481 | The following projects, were created with different goals and tradeoffs in mind, so every comparison 482 | and analogy is subjective and can be argued. The presence of some operator is not necessary good, as 483 | well as the abscence is not necessary bad. 484 | 485 | Note, that primitives differ for each library. In descriptions, we broadly refer to all the "observable 486 | primitives" as **streams***, though, technically speaking, some of them are rather stream-like entities. 487 | 488 | To find something, search for a term you know. 489 | 490 | ## API 491 | 492 | ### Create 493 | 494 | #### Create an empty stream 495 | 496 | * KefirJS: [`never`](http://kefirjs.github.io/kefir/#never) 497 | * MostJS: [`empty`](https://github.com/cujojs/most/blob/master/docs/api.md#mostempty) 498 | * RxJS: [`of`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/of.md) 499 | * XStream: [`empty`](https://github.com/staltz/xstream#of) 500 | 501 | #### Create a stream from a single value 502 | 503 | * KefirJS: [`constant`](http://kefirjs.github.io/kefir/#constant) 504 | * MostJS: [`of`](https://github.com/cujojs/most/blob/master/docs/api.md#mostjust), [`just`](https://github.com/cujojs/most/blob/master/docs/api.md#mostjust) 505 | * RxJS: [`of`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/of.md), [`just`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/return.md) 506 | * XStream: [`of`](https://github.com/staltz/xstream#of) 507 | 508 | #### Create a stream from an array 509 | 510 | * KefirJS: [`sequentially`](http://kefirjs.github.io/kefir/#sequentially) 511 | * MostJS: [`from`](https://github.com/cujojs/most/blob/master/docs/api.md#mostfrom) 512 | * RxJS: [`from`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/from.md), [`of`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/of.md) 513 | * XStream: [`from`](https://github.com/staltz/xstream#from), [`fromArray`](https://github.com/staltz/xstream#fromArray) 514 | 515 | #### Create a stream from a promise 516 | 517 | * KefirJS: [`fromPromise`](http://kefirjs.github.io/kefir/#from-promise) 518 | * MostJS: [`fromPromise`](https://github.com/cujojs/most/blob/master/docs/api.md#mostfrompromise) 519 | * RxJS: [`fromPromise`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/frompromise.md) 520 | * XStream: [`fromPromise`](https://github.com/staltz/xstream#fromPromise) 521 | 522 | #### Create a stream from an event 523 | 524 | * KefirJS: [`fromEvents`](http://kefirjs.github.io/kefir/#from-event) 525 | * MostJS: [`fromEvent`](https://github.com/cujojs/most/blob/master/docs/api.md#mostfromevent) 526 | * RxJS: [`fromEvent`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/fromevent.md) 527 | * XStream: [`fromEvent`](https://github.com/staltz/xstream/blob/master/EXTRA_DOCS.md#fromEvent) 528 | 529 | #### Create a stream from a callback 530 | 531 | * KefirJS: [`stream`](http://kefirjs.github.io/kefir/#stream), [`fromCallback`](http://kefirjs.github.io/kefir/#from-callback), [`fromNodeCallback`](http://kefirjs.github.io/kefir/#from-node-callback), [`fromPoll`](http://kefirjs.github.io/kefir/#from-poll) 532 | * MostJS: `new Stream` 533 | * RxJS: `new Observable`, `bindCallback`, `bindNodeCallback` 534 | * XStream: `? (make a promise first)` 535 | 536 | #### Prepend a stream with a value 537 | 538 | * KefirJS: [`merge`](http://kefirjs.github.io/kefir/#merge) `+` [`constant`](http://kefirjs.github.io/kefir/#constant) 539 | * MostJS: `startWith` 540 | * RxJS: `startWith` 541 | * XStream: `startWith` 542 | 543 | ### Transform (data events) 544 | 545 | #### Map value one-to-one 546 | 547 | * KefirJS: [`map`](http://kefirjs.github.io/kefir/#map) 548 | * MostJS: `map`, `constant` 549 | * RxJS: `map`, `mapTo` 550 | * XStream: `map` 551 | 552 | #### Filter value by a predicate 553 | 554 | * KefirJS: [`filter`](http://kefirjs.github.io/kefir/#filter) 555 | * MostJS: `filter` 556 | * RxJS: `filter` 557 | * XStream: `filter` 558 | 559 | #### Skip N initial values 560 | 561 | * KefirJS: [`skip`](http://kefirjs.github.io/kefir/#skip) 562 | * MostJS: `skip` 563 | * RxJS: `skip` 564 | * XStream: `drop` 565 | 566 | #### Take N initial values 567 | 568 | * KefirJS: [`take`](http://kefirjs.github.io/kefir/#take) 569 | * MostJS: `take` 570 | * RxJS: `take` 571 | * XStream: `take` 572 | 573 | #### Make a value from an accumulator and a next value 574 | 575 | * KefirJS: [`scan`](http://kefirjs.github.io/kefir/#scan) 576 | * MostJS: `scan` 577 | * RxJS: `scan` 578 | * XStream: `fold` 579 | 580 | ### Combine 581 | 582 | #### Merge multiple streams together 583 | 584 | * KefirJS: [`merge`](http://kefirjs.github.io/kefir/#merge) 585 | * MostJS: `merge` 586 | * RxJS: `merge` 587 | * XStream: `merge` 588 | 589 | Pay attention that Kefir's `merge` accepts arrays while others are variadic. 590 | 591 | #### Combine multiple streams together 592 | 593 | * KefirJS: [`combine`](http://kefirjs.github.io/kefir/#combine) 594 | * MostJS: `combine` 595 | * RxJS: `combineLatest` 596 | * XStream: `combine` 597 | 598 | #### Sample a stream by another stream 599 | 600 | * KefirJS: [`combine`](http://kefirjs.github.io/kefir/#combine), [`sampledBy`](http://kefirjs.github.io/kefir/#obs-sampled-by) 601 | * MostJS: `sample`, `sampleWith` 602 | * RxJS: `sample`, `withLatestFrom` 603 | * XStream: `sampleCombine` 604 | 605 | #### Chain streams sequentially 606 | 607 | * KefirJS: [`flatMapConcat`](http://kefirjs.github.io/kefir/#flat-map-concat) 608 | * MostJS: `concatMap` 609 | * RxJS: `concatMap` 610 | * XStream: `map + flattenSequentially` 611 | 612 | --- 613 | 614 | ### Create 615 | 616 | Create stream from non-stream values. 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 |
KefirJSMostJSRxJSXStream
intervalperiodicinterval + mapperiodic
repeatof + R.rangerepeatof + R.range
?iterategenerate?
?generategenerate?
650 | 651 | ### Mapper 652 | 653 | Modify events one to one. 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 |
KefirJSMostJSRxJSXStream
delaydelaydelaycombine(delay(500))
– (map)timestamptimestamp– (map)
675 | 676 | ### Transforms 677 | 678 | Modify events * to *. 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 |
MostJSRxJSXStream
chain / flatMapflatMapmap + flattenConcurrently
map + switchswitchMap / flatMapLatestmap + flatten
joinmergeAllflatten
loopscan + mapfold + map
– (custom)bufferWithCount?
712 | 713 | ### Filters 714 | 715 | Skip events by predicate or signal. 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 |
MostJSRxJSXStream
skipRepeatsdistinctUntilChangeddropRepeats
skipRepeatsWith– (scan)dropRepeats
sliceskip + takedrop + take
skipWhileskipWhilefold + filter + map
takeWhiletakeWhilefilter + endWhen
since / skipUntilskipUntilfold + filter + map
until / takeUntiltakeUntilfilter + endWhen
duringwindow + take(1)?
764 | 765 | ### Combinators 766 | 767 | Combine multiple streams into single. 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 |
MostJSRxJSXStream
zipzip?
concatconcatconcat
apcombineLatest?
791 | 792 | ### Side effects 793 | 794 | Produce side effect for every event. 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 |
MostJSRxJSXStream
tapdo / tapdebug
808 | 809 | ### Ending 810 | 811 | Operators which target **end** event somehow. 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 |
MostJSRxJSXStream
emptyemptyempty
nevernevernever
continueWith?concat
835 | 836 | ### Concurrency 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 |
MostJSRxJS
– (custom)amb / race
848 | 849 | ### History 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 |
MostJSRxJS
– (custom)
860 | 861 | ### Design diffs 862 | 863 | #### RxJS 864 | 865 | 1. Three primitives: `Observer`, `Observable`, `Subject`. 866 | 2. Observables end on error. 867 | 3. Provides API to handle errors. 868 | 3. Does not provide API to handle ending. 869 | 870 | #### KefirJS 871 | 872 | 1. Two primitives: `Stream` and `Property` (like XStream). 873 | 2. Observables does not end on error (by default). 874 | 3. Provides API to handle errors. 875 | 4. Provides API to handle ending. 876 | 877 | #### MostJS 878 | 879 | 1. One primitive: `Stream` (+ community-driven). 880 | 2. Separate packages for [subject-like](https://github.com/TylorS/most-subject) and [property-like](https://github.com/mostjs/hold) primitives. 881 | 3. Provides API to handle errors. 882 | 4. Provides API to handle ending. 883 | 884 | #### XStream 885 | 886 | 1. Two primitives: `Stream` and `MemoryStream` (like KefirJS). 887 | 2. Always multicast. A Stream is like an RxJS Subject. 888 | 3. Streams end on error. 889 | 890 | #### Common 891 | 892 | RxJS does not emit initial `scan` value as event (use `startWith` for that). 893 | 894 | ```js 895 | Rx.Observable.interval(100).map(x => 1) 896 | .scan(add, 0); 897 | .subscribe(console.log); // 1--2--3--... 898 | 899 | Most.periodic(100, 1) 900 | .scan(add, 0); 901 | .observe(console.log); // 0--1--2--3--... 902 | ``` 903 | 904 | ### Found docs / API quirks 905 | 906 | #### MostJS 907 | 908 | `startWith` vs `sampleWith` vs `continueWith` + `recoverWith` vs `skipRepeatsWith`
909 | (val vs none vs func vs stream) 910 | 911 | `tap` is listed in "Transform" section. 912 | 913 | #### RxJS 914 | 915 | `startWith` is listed in "Combine" section. 916 | 917 | `mergeAll` is listed in "Combine" section. 918 | 919 | `distinct` is not listed in "Filtering" section. 920 | 921 | `takeUntil` is not listed in "Filtering" section. 922 | 923 | `just` / `return` should be deprecated in favor of `of`. 924 | 925 | `fromArray` should be deprecated in favor of `from`. 926 | 927 | ### Links 928 | 929 | [bacon-vs-kefir](https://github.com/rpominov/kefir/blob/master/bacon-vs-kefir-api.md) – BaconJS vs KefirJS API comparison 930 | 931 | [dataflows](https://github.com/ivan-kleshnin/dataflows) – web arch. dataflow comparison 932 | 933 | [stream-conversions](https://github.com/TylorS/stream-conversions) – tool for cross-library stream conversions 934 | 935 | ### Additional Read 936 | 937 | https://github.com/cujojs/most/issues/171 938 | 939 | https://twitter.com/rpominov/status/689566111734599683 940 | 941 | https://github.com/zenparsing/es-observable/issues/66 942 | 943 | 944 | --------------------------------------------------------------------------------