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

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

  • Upload
    solit

  • View
    175

  • Download
    7

Embed Size (px)

DESCRIPTION

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

Citation preview

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. Победа над асинхронностью и вложенностью, Русакович Виктор

Вопросы?