CYCLE.JS A Functional reactive UI framework Nikos Kalogridis @nikoskalogridis
WHY ANOTHER FRAMEWORK? Programming is hard! Complexity of Web apps is growing exponentially Asynchronous programming complicates things even more
CYCLE.JS ANDRÉ MEDEIROS (AKA. ANDRÉ STALTZ)
CYCLE.JS FEATURES Functional Reactive Unidirectonal flow of data Virtual DOM A Cycle.js program is a pure function - no side effects
CYCLE.JS HISTORY Nov-2014 - Initial commit on github based on RxJs Nov-2015 - A fork of the project was made based most.js Jun-2016 - Merged back this time supporting xstream, Rxjs v4, Rxjs v5 and most.js TC39 Observable proposal Feb-2017 - Dropped stream adapters and now uses Observable to convert between streams. Also dropped support for Rxjs v4
FUNCTIONAL PROGRAMMING Declarative instead of imperative Pure functions Immutability
MAP Returns a new array with the result of applying a function on each element of the array var myArray = [1, 2, 3, 4, 5]; myArray.map(function (value) { return value + 1; }); // -> [2, 3, 4, 5, 6]
FILTER Returns a new array with all elements that pass the test implemented by the provided function var myArray = [1, 2, 3, 4, 5]; myArray.filter(function (value) { return value < 4; }); // -> [1, 2, 3]
REDUCE Reduces the elements to a single value applying a function to each of them var myArray = [1, 2, 3, 4, 5]; myArray.reduce(function (acc, value) { return acc + value; }, 0); // -> 15
IMPERATIVE VS DECLARATIVE Given an array of numbers return the numbers that are less than 4 and add to each of those 10 var myArray = [1, 2, 3, 4, 5]; var result = []; var i = 0; for (i; i < myArray.length; i += 1) { if (myArray[i] < 4) { result.push(myArray[i] + 10); } } var myArray = [1, 2, 3, 4, 5]; var result = myArray .filter((value) => value < 4) .map((value) => value + 10);
HIGHER ORDER FUNCTION a function that takes a function as a parameter or returns a function or both
HIGHER ORDER FUNCTION EXAMPLES function add(amount) { return function (value) { return value + amount; } } function lessThan(amount) { return function (value) { return value < amount; } } var result = myArray.filter(lessThan(4)).map(add(10));
PURE FUNCTION its return value is affected only by its passed parameters and has no side effects
PURE VS IMPURE var a = 10; function impure(x) { return x + a; } function pure(x, y) { return x + y; }
SIDE EFFECTS var a = 0; function impure(x) { a = x + a; } function impure(x) { console.log(x); return x + 1; }
ASYNCHRONOUS PROGRAMMING IN JAVASCRIPT Callbacks Promises Generators / yield Async / await Observables
CALLBACKS var counter = 0; function callback() { counter += 1; } document .getElementById('myButton') .addEventListener('click', callback); var xhr = new XMLHttpRequest(); xhr.open('GET', '/server', true); xhr.onload = function () { // Request finished. Do processing here. };
PROMISES var requestPromise = fetch({url: 'http://www.google.com'}); requestPromise .then(function (response) { // do something with the response }) .catch(function (error) { // handle the error });
GENERATORS / YIELD function* foo () { var index = 0; while (index < 2) { yield index++; } } var bar = foo(); console.log(bar.next()); // { value: 0, done: false } console.log(bar.next()); // { value: 1, done: false } console.log(bar.next()); // { value: undefined, done: true }
ASYNC / AWAIT async function save(Something) { try { await Something.save(); } catch (ex) { //error handling } console.log('success'); }
OBSERVABLE // data$ is an Observable object var subscription = data$.subscribe( { next: function (value) { // handle next value }, error: function (error) { // handle error }, complete: function () { // finished so do cleanup... } } );
REACTIVE PROGRAMMING is programming with data streams (synchronous or asynchronous) on top of that you are given an amazing toolbox of functions to combine, create, filter any of those streams
REACTIVE LIBRARIES IN JAVASCRIPT Bacon.js Rxjs kefir.js most.js xstream
RXJS EXAMPLE import Rx from 'rxjs/Rx'; let counter = 0; const increaseButton = document.querySelector('#increase'); const increaseClick$ = Rx.Observable.fromEvent(increaseButton, 'click'); increaseClick$.subscribe({ next: function () { // click received counter += 1; console.log(counter); } });
RXJS EXAMPLE REVISED import Rx from 'rxjs/Rx'; const increaseButton = document.querySelector('#increase'); const increaseClick$ = Rx.Observable.fromEvent(increaseButton, 'click'); const counter$ = increaseClick$ .mapTo(1) // always maps to a constant value .scan((acc, value) => acc + value, 0); // hint: reduce counter$.subscribe({ next: function (counter) { // new count event received console.log(counter); } });
OTHER TYPES OF STREAMS Rx.Observable.from([1, 2, 3, 4, 5]) .filter((x) => x < 4) .map((x) => x + 10) .subscribe({ next: (value) => console.log(value), complete: () => console.log('done') }); // -> // 11 // 12 // 13 // done
PROMISE AS A STREAM const myPromise = new Promise((resolve) => resolve('hello')); Rx.Observable.from(myPromise) .subscribe({ next: (value) => console.log(value), complete: () => console.log('done') }); // -> // hello // done
COMBINING STREAMS const data1$ = Rx.Observable.from([1, 2, 3]); const data2$ = Rx.Observable.from([6, 7, 8]); Rx.merge(data1$, data2$) .subscribe({ next: (value) => console.log(value) }); // -> // 1 // 6 // 2 // 7 // 3 // 8
MERGE OPERATOR
CYCLE.JS MODEL Human Senses Actuators InputOutput Computer
A CYCLE.JS PROGRAM IS A PURE FUNCTION function cycleProgram(sources) { return sinks; }
function main(sources) { const model$ = sources .DOM.select('.increase').events('click') .mapTo(1).fold((acc, value) => acc + value, 0); const vtree$ = model$.map((value) => div([ button('.increase', 'Increase'), span(value) ]) ); return {DOM: vtree$}; } Cycle.run(main, { DOM: makeDOMDriver('#app') });
NO SIDE EFFECTS Sources Sinks main() DOM side effects HTTP side effects Other side effects pure dataflow
IN CYCLE.JS
DEMO
PROS Truly reactive programming style Declarative UI design Fast - thanks to Snabdom and xstream Fractal state management
CONS Brain rewiring for using functional reactive style Relatively small community compared to React or Angular Steep learning curve especially on stream libraries Lacks a complete UI component library (as of today)
USEFUL LINKS https://cycle.js.org/ http://widdersh.in/tricycle/ https://github.com/cyclejs-community https://gitter.im/cyclejs/cyclejs https://github.com/staltz/cycle-onionify https://github.com/cyclejs-community/cyclic-router http://staltz.com
QUESTIONS
THANK YOU

Cycle.js - Functional reactive UI framework (Nikos Kalogridis)