Solit 2014, Реактивный Javascript. Победа над асинхронностью и...

46
Реактивные расширения для JavaScript... ...и пусть события сами идут

description

Виктор Русакович, Минск, Web-developer c 6-ти летним опытом разработки, компания GP Software.travel «Реактивный JavaScript. Победа над асинхронностью и вложенностью». Development секция. Для разработчиков. Высокий уровень подготовки. «Непрерывная интеграция сложного проекта. Кто всё сломал?». IT секция. Agile отделение. Для всех уровней подготовки.

Transcript of Solit 2014, Реактивный Javascript. Победа над асинхронностью и...

Page 1: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Реактивные расширения для

JavaScript......и пусть события сами идут

Page 2: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Где мы используем события?

ВЕЗДЕ

Page 3: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Что не так с событиями?

● как компоновать?● как фильтровать?● как собирать данные от разных

событий?● как не сойти с ума от

асинхронности?● как не строить Пирамиды Обратных

Вызовов?● … (еще примерно 42 пункта)

Page 4: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

О ужасный callback!

$('#some-element').animate({ width: 100, height: 50}, { duration: 300, complete: function() { // Step 2: $('#another-element').fadeOut(300, function() { // Step 3: setTimeout(function() { // Step 4: $.ajax({ url: 'http://google.com', }).done(function() { // Step 5: setTimeout(function() { // Step 6: $('#third-element').remove(); }, 250); }); }, 300); }); }});

Page 5: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

О ужасный callback!

step1(function (value1) { step2(value1, function(value2) { step3(value2, function(value3) { step4(value3, function(value4) { // Do something with value4 }); }); });});

Page 6: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

О ужасный callback! (и доступ к данным)

step1(function (value1) { step2(value1, function(value2) { step3(value2, function(value3) {

if (value2 === 4) return null step4(value3, function(value4) { if (value2 > value3) work() }); }); });});

Page 7: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Варианты решения а-ля promise...Q.fcall(step1) .then(step2) .then(step3) .then(step4) .then(function (value4) { // Do something with value4 }) .done();

https://github.com/kriskowal/q/

A tool for making and composing asynchronous promises in JavaScript (282 362 forks at Github).

Page 8: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

...или настоящими promise

function successFunc(){ console.log( “success!” ); }

function failureFunc(){ console.log( “failure!” ); }

$.when(

$.ajax("/main.php" ),

$.ajax("/modules.php" ),

$.ajax(“/lists.php” )

).then( successFunc, failureFunc );

Все равно не хватает контроля над данными!

Page 9: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Reactive Extensions for JS

...is a library to compose asynchronous and event-based programs using

observable collections and LINQ-style query operators.

Page 10: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Реактивные расширения

...библиотека для создания асинхронных и основанных на событиях программ используя

наблюдаемые коллекции и LINQ операторы.

Page 11: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Состав RxJS:

● объекты для представления асинхронных потоков данных

● операторы для создания, фильтрации и управления подобными объектами и данными внутри них

● немного магии

Page 12: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Реактивное программирование

- парадигма, ориентированная на потоки данных и распространение изменений.

Это означает, что должна существовать возможность легко выражать статические и динамические потоки данных, а также то, что выполняемая модель должна автоматически распространять изменения сквозь поток данных.

Page 13: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

2 примера реактивности из жизни1. Excel 2. Ищем работу:

обзванивать вакансииpull vs

разместить резюме ждать звонков

push

Page 14: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Основа идеологии

НаблюдательObserver

Наблюдаемое (поток)

Observable

подписывается (subscribe) ⇒ ⇐ присылает сообщения (onNext)

Page 15: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Наблюдаемая последовательнсть

Page 16: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

RxJS против не-RxJS

$

('button').clickAsObserva

ble()

.skip(2)

.take(2)

.timeInterval()

.doAction(flickerButton)

.subscribe(logClicks)

var i= 0, lastTs = new Date(), nowTs$('button').click(function(){ i++; if (i<=2 || i>=4) return nowTs = new Date() flickerButton() logClicks(diff(lastTs, nowTs))})

Page 17: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

query

Используем привычные функции

Array● concat● every● filter● map● reduce● some● forEach

Observable● concat● all● where● select● aggregate● any● subscribe

Page 18: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Поддержка родных событий jQuery•bind - bindAsObservable

•delegate - delegateAsObservable

•live - liveAsObservable

•on - onAsObservable

•$.Deferred.toObservable /

Rx.Observable.toDeferred

Page 19: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Мышь и клавиатура

•change - changeAsObservable

•click - clickAsObservable

•dblclick - dblclickAsObservable

•focus - focusAsObservable

•focusin - focusinAsObservable

•focusout - focusoutAsObservable

•hover - hoverAsObservable

•keydown - keydownAsObservable

•keypress - keypressAsObservable

•keyup - keyupAsObservable

•load - loadAsObservable

•mousedown - mousedownAsObservable

•mouseenter - mouseenterAsObservable

•mouseleave - mouseleaveAsObservable

•mousemove - mousemoveAsObservable

•mouseout - mouseoutAsObservable

•mouseenter - mouseenterAsObservable

•mouseleave - mouseleaveAsObservable

•mousemove - mousemoveAsObservable

•mouseout - mouseoutAsObservable

Page 20: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Ajax и анимация

• ajax - ajaxAsObservable

• get - getAsObservable

• getJSON - getJSONAsObservable

• getScript - getScriptAsObservable

• post - postAsObservable

• animate - animateAsObservable

• fadeIn - fadeInAsObservable

• fadeOut - fadeOutAsObservable

• fadeTo - fadeToAsObservable

• fadeToggle - fadeToggleAsObservable

• hide - hideAsObservable

• show - showAsObservable

• slideDown - slideDownAsObservable

• slideToggle - slideToggleAsObservable

• slideUp - slideUpAsObservable

Page 21: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Состав RxJS:

● объекты для представления асинхронных потоков данных

● операторы для создания, фильтрации и управления подобными объектами и данными внутри них

● немного магии

Page 22: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Операторы объединения

● Amb● Merge● Concat● CombineLatest● Zip● Repeat

stream y

stream x

resultresult = fn(x, y, …, n)

Page 23: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Операторы фильтрации и выбора● where (filter) / whereTrue / whereFalse● take / takeUntil / takeWhile● skip / skipUntill / skipWhile● select (map) / selectMany /

selectProperty

stream x

resultresult = fn.apply(x)

Page 24: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Операторы для данных

● scan● count● min● max● groupBy● distinct / distinctUntilChanged● throttle

Page 25: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Временные диаграммы

Page 26: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Временные диаграммы вживую

j q ut

Page 27: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

result = source.throttle(1500)

jqu

jqu

source

resultjqu

jque

jque

1,5 сек 1,5 сек

0,3 сек

Page 28: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

.select()negativeStream = stream.select(function(value) { return -value });

negativeStream = stream.select(invert);function invert(value) { return -value });

Page 29: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

.where()negativeStream = stream .where(function(value) { return value % 2 == 0 });

negativeStream = stream.where(isEven);

Page 30: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

xStream.merge(yStream)

Page 31: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

xStream.combineLatest(yStream)

Page 32: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

x.zip(y)

Page 33: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

.bufferWithTime(3000)

.bufferWithCount(3)

.bufferWithTimeOrCount(3000, 3)

Page 34: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

dots.delay(1000)

Page 35: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Операторы - over 9000aggregateallambandanyasObservableaveragebufferbufferWithCountbufferWithTimebufferWithTimeOrCountcase | switchCasecatch | catchExceptioncatch | catchExceptioncombineLatestconcatconnectcontainscountcreatecreateWithDisposabledefaultIfEmptydeferdelaydelayWithSelectordematerializedistinctdistinctUntilChangeddo | doActiondoWhileelementAtelementAtOrDefaultempty

everyexpandfilterfinally | finallyActionfindfindIndexfirstfirstOrDefaultflatMapflatMapLatestfor | forInforkJoinfromArraygenerategenerateWithAbsoluteTimegenerateWithRelativeTimegroupBygroupByUntilgroupJoinif | ifThenignoreElementsintervalisEmptyjoinlastlastOrDefaultmanySelectmapmaxmaxBymergemergeObservablemin

minBymulticastneverobserveOnonErrorResumeNextonErrorResumeNextpluckpublishpublishLastpublishValuerangereducerefCountrepeatrepeatreplayretryreturn | returnValuesamplescanselectselectManyselectSwitchsinglesingleOrDefaultskipskipLastskipLastWithTimeskipUntilskipWhilesomestartstartWith

subscribesubscribeOnsumswitch | switchLatesttaketakeLasttakeLastBuffertakeLastBufferWithTimetakeLastWithTimetakeUntiltakeWhilethrottlethrottleWithSelectorthrow | throwExceptiontimeIntervaltimeouttimeoutWithSelectortimertimestamptoArraytoAsyncusingwhenwherewhile | whileDowindowwindowWithCountwindowWithTimewindowWithTimeOrCountzip

Page 36: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Языки с библиотеками RX

1.node.js2. Java3.Ruby4.Python5.ObjectiveC6.C++7. ...8.https://github.com/Reactive-Extensions

Page 37: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Демо

закрепим в jsFiddle полученные знания

Page 38: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Большое приложение

основанное на RxJS

Page 39: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

selectedItem => {id: 1, title: “Матрешка”}loadPanelStatus => {status: true}pageSelection => {page: 4}

loadPanelStatus => {status: true}couponChanges => {id: undefined}itemRemoval => {id: 1}

Модуль корзины

Модуль каталога

КонтролерselectedItem {id: 1}

selectedItemloadPanelStatus

couponChangesitemRemoval

inputstreams

itemRemoval {id: 2}

Page 40: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Модуль корзины

Модуль каталога

Контролер

couponChanges .selectPropert(‘id’) => {id: “couponId”} => “couponId” .select(affectedItems) => “couponId” => [1,2,4] .subscribe(updateItemsPrice) itemRemoval .skipUntil(loadPanelStatus.whereTrue()) .takeUntil(loadPanelStatus.whereFalse()) .subscribe(markItemAsRemoved) <= {id: 1}

function affectedItems(coupon) { return $(‘.items.’+coupon).map(function(item){ return $(item).data(‘id’) }) }

selectedItem {id: 1}

selectedItemloadPanelStatus

couponChangesitemRemoval

inputstreams

itemRemoval {id: 2}

Page 41: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Вредные советы

● одноразовые потоки● потоки-сироты● превращаем все события в потоки,

все!● общие названия потоков (dataStream)● свои операторы не читая

документацию

Page 42: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Полезные советы

● простые данные в сообщениях● говорящие названия для потоков● простая логика для объединения● промежуточные потоки● функциональный подход

Page 43: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Фото кода

Page 44: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Литература:

1. http://www.introtorx.com/Content/v1.0.10621.0/00_Foreword.html

2. https://github.com/Reactive-Extensions

3. https://github.com/Reactive-Extensions/RxJS/tree/master/doc

4. http://blogs.microsoft.co.il/blogs/bnaya/archive/2010/02/25/rx-for-beginners-toc.aspx

5. http://www.slideshare.net/mattpodwysocki/cascadiajs-dont-cross-the-streams

6. http://www.slideshare.net/panesofglass/rx-workshop

7. http://www.infoq.com/reactive-extensions/

8. http://mywebbasedcomputer.com/users/johngslater/tech/rx/bubbleDiagrams.html

9. https://github.com/Netflix/RxJava/wiki/Observable-Utility-Operators

10. Matthew Podwysocki

Page 45: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Спасибо!

Виктор Русакович из Минска, Беларусь

[email protected]

Page 46: Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, Русакович Виктор

Вопросы?