SlideShare a Scribd company logo
Programming UI with FRP and Bacon.js

Vyacheslav Voronchuk
voronchuk@wm-software.com
Skype: voronhukvk
http://ua.linkedin.com/in/voronchuk/
What is FRP?
l 

Sources of data

l 

Events

l 

Side-effects

l 

Switching
Javascript FRP frameworks
l 

Elm

l 

Flapjax

l 

Javelin

l 

RxJS

l 

others
FrontendLab: Programming UI with FRP and Bacon js - Вячеслав Ворончук
How it helps?
l 

Callback spaghetti

l 

Refactoring

l 

New features and tweaks
FlatMap

$.ajax({ url: “/items” }).done(function(items) {
if(items.error) {
return handleError(items.error);
}

$.each(items, function(item) {
$.ajax({ url: “/item/” + item.id }).done(function(item) {
if(item.error) {
return handleError(item.error);
}
renderItem(item, function(itemEl) {
itemEl.children('.delete').click(function() {
$.ajax({ url: “/item/” + item.id, type:
'DELETE' }).done(function(response) {
if(response.error) {
return handleError(response.error);
}
itemEl.remove();
});
});
});
});

});

});
FlatMap
isError = function(serverResponse) { return typeof serverResponse.error !== 'undefined' }
isNotError = function(serverResponse) { return !isError(serverResponse); }
$allItems = Bacon.fromPromise($.ajax({ url: “/items” }));
$errors = $allItems.filter(isError);
$items = $allItems.filter(isNotError).flatMap(function (item) {
return Bacon.fromPromise($.ajax({ url: “/item” + item.id }));
});
$errors.merge($items.filter(isError));
$renderedItems = $items.filter(isNotError).flatMap(function(item) {
return Bacon.fromCallback(renderItem, item);
});
$renderedItemsDeleteClicks = $renderedItems.flatMap(function(renderedItem){
return Bacon.fromEventTarget(renderedItem.children('.delete'), 'click', function(event) {
return renderedItem;
});
});
$deleteItemRequest = $renderedItemsDeleteClicks.flatMap(function(renderedItem) {
return Bacon.fromPromise($.ajax({ url: “/item” + renderedItem.data('id'), type: 'DELETE' }));
});
$errors.merge($deleteItemRequest.filter(isError));
$errors.onValue(handleError);
$deleteItemRequest.filter(isNotError).onValue('.remove');
When and Combine
isError = function(serverResponse) { return typeof serverResponse.error !== 'undefined' }
isNotError = function(serverResponse) { return !isError(serverResponse); }
$items = Bacon.fromPromise($.ajax({ url: “/items” }));
$renderedItems = $items.filter(isNotError).flatMap(function(item) {
return Bacon.fromCallback(renderItem, item);
});
$quantity = $renderedItems.flatMap(function(element) {
return Bacon.fromEventTarget($(element).children('.quantity'), 'change').map(function(event) {
return [element, $(element).val()];
});
});
$price = $quantity.map(function(data) {
return $(data[0]).data('price') * data[1];
});
$refreshClick = Bacon.fromEventTarget($('#refresh_cart'), 'change');
Bacon.when(
[$refreshClick, $quantity, $price], function(event, data, price) {
$(data[0]).children('.internal-price').text(price);
$(data[0]).children('.price').text(price);
},
[$quantity, $price], function(data, price) {
$(data[0]).children('.internal-price').text(price);
}
);
Bus

var $deleteItem = new Bacon.Bus();
$deleteItem.plug(Bacon.fromEventTarget($('.delete'), 'click'));
$deleteItem.map('.target.remove');
$deleteItem.push($('item1'));
Bus
var chopsticks = [new Bacon.Bus(), new Bacon.Bus(), new Bacon.Bus()]
var hungry = [new Bacon.Bus(), new Bacon.Bus(), new Bacon.Bus()]
var eat = function(i) {
return function() {
setTimeout(function() {
chopsticks[i].push({})
chopsticks[(i+1) % 3].push({})
}, 1000);
return 'philosopher ' + i + ' eating'
}
}
var dining = Bacon.when(
[hungry[0], chopsticks[0], chopsticks[1]], eat(0),
[hungry[1], chopsticks[1], chopsticks[2]], eat(1),
[hungry[2], chopsticks[2], chopsticks[0]], eat(2)
).log()
// make all chopsticks initially available
chopsticks[0].push({}); chopsticks[1].push({}); chopsticks[2].push({})
// make philosophers hungry in some way, in this case we just push to their bus
for (var i = 0; i < 3; i++) {
hungry[0].push({}); hungry[1].push({}); hungry[2].push({})
}
Usage in Node.js
getInvoiceStream = (id) -> Bacon.fromNodeCallback Invoice, 'findOne', id: id
getInvoiceDataStream = ($invoice) -> $invoice.flatMap (invoice) ->
Bacon.fromNodeCallback invoice, 'toDeepJSON'
# Load Invoice and it's deps
get: (req, res) ->
$invoice = getInvoiceStream req.param 'id'
$invoiceData = getInvoiceDataStream invoice
$invoiceData.onValue _.bind(res.json, res)
$errors = Bacon.mergeAll $invoice.errors(), $invoiceData.errors()
$errors.onError _.bind(res.send, res, 500)
# Generate PDF export
pdf: (req, res) ->
$invoice = getInvoiceStream req.param 'id'
$invoiceData = getInvoiceDataStream $invoice
$invoiceRender = $invoiceData.map renderInvoicePDF
$invoiceRenderData = $invoiceRender.flatMap (pdf) -> Bacon.fromCallback pdf, 'output'
$invoiceRenderData.onValue _.bind(res.end, res)
$errors = Bacon.mergeAll $invoice.errors(), $invoiceData.errors()
$errors.onError _.bind(res.send, res, 500)
AJAX Search
// Stream of search queries
var $query = $("#search").asEventStream("keyup").map(function(event) {
return $(event.srcElement).val();
}).skipDuplicates();
// Search result strings
var $results = $query.throttle(500).flatMapLatest(function(query) {
return Bacon.fromPromise($.ajax("/search/" + query))
}).mapError("Search error");
// Render results
$results.onValue(function(result) {
$("#results").html(result);
});
// Search status
var searchStatus = $query.map(true).merge($results.map(false)).skipDuplicates().toProperty(false);
Debug
l 

Observable.log()

l 

Observable.toString()

l 

Observable.deps()

l 

Observable.internalDeps()

l 

Bacon.spy(f)
Notices
l 

onValue

l 

fromArray
Links
l 

Github page: https://github.com/baconjs/bacon.js

l 

Bacon.js blog: http://baconjs.blogspot.fi/

l 

Snake game: http://philipnilsson.github.io/badness/

l 

Worzone game: http://juhajasatu.com/worzone/
FrontendLab: Programming UI with FRP and Bacon js - Вячеслав Ворончук
Ad

Recommended

FRP and Bacon.js
FRP and Bacon.js
Starbuildr
 
History of jQuery
History of jQuery
jeresig
 
Introduction to ECMAScript 2015
Introduction to ECMAScript 2015
Tomasz Dziuda
 
Beyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS Apps
Rebecca Murphey
 
Jqeury ajax plugins
Jqeury ajax plugins
Inbal Geffen
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Tsuyoshi Yamamoto
 
Building Single Page Apps with Backbone.js, Coffeescript and Rails 3.1
Building Single Page Apps with Backbone.js, Coffeescript and Rails 3.1
Vagmi Mudumbai
 
dplyr and torrents from cpasbien
dplyr and torrents from cpasbien
Romain Francois
 
Python Developer's Daily Routine
Python Developer's Daily Routine
Maxim Avanov
 
Jquery Fundamentals
Jquery Fundamentals
Rebecca Murphey
 
JQuery
JQuery
SelmanJagxhiu
 
BVJS
BVJS
Rebecca Murphey
 
Everyday's JS
Everyday's JS
Adib Mehedi
 
dplyr use case
dplyr use case
Romain Francois
 
Jquery Best Practices
Jquery Best Practices
brinsknaps
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Stripe
 
Kotlin: Let's Make Android Great Again
Kotlin: Let's Make Android Great Again
Taeho Kim
 
jQuery Namespace Pattern
jQuery Namespace Pattern
Diego Fleury
 
(안드로이드 개발자를 위한) 오픈소스 라이브러리 사용 가이드
(안드로이드 개발자를 위한) 오픈소스 라이브러리 사용 가이드
Taeho Kim
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
MongoDB
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
Jarod Ferguson
 
레진코믹스가 코틀린으로 간 까닭은?
레진코믹스가 코틀린으로 간 까닭은?
Taeho Kim
 
dplyr
dplyr
Romain Francois
 
Delivering a Responsive UI
Delivering a Responsive UI
Rebecca Murphey
 
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Puppet
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
MongoDB
 
Drupal, meet Assetic
Drupal, meet Assetic
Kris Wallsmith
 
RubyBarCamp “Полезные gems и plugins”
RubyBarCamp “Полезные gems и plugins”
apostlion
 
jQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journey
Huiyi Yan
 
jQuery: Events, Animation, Ajax
jQuery: Events, Animation, Ajax
Constantin Titarenko
 

More Related Content

What's hot (20)

Python Developer's Daily Routine
Python Developer's Daily Routine
Maxim Avanov
 
Jquery Fundamentals
Jquery Fundamentals
Rebecca Murphey
 
JQuery
JQuery
SelmanJagxhiu
 
BVJS
BVJS
Rebecca Murphey
 
Everyday's JS
Everyday's JS
Adib Mehedi
 
dplyr use case
dplyr use case
Romain Francois
 
Jquery Best Practices
Jquery Best Practices
brinsknaps
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Stripe
 
Kotlin: Let's Make Android Great Again
Kotlin: Let's Make Android Great Again
Taeho Kim
 
jQuery Namespace Pattern
jQuery Namespace Pattern
Diego Fleury
 
(안드로이드 개발자를 위한) 오픈소스 라이브러리 사용 가이드
(안드로이드 개발자를 위한) 오픈소스 라이브러리 사용 가이드
Taeho Kim
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
MongoDB
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
Jarod Ferguson
 
레진코믹스가 코틀린으로 간 까닭은?
레진코믹스가 코틀린으로 간 까닭은?
Taeho Kim
 
dplyr
dplyr
Romain Francois
 
Delivering a Responsive UI
Delivering a Responsive UI
Rebecca Murphey
 
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Puppet
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
MongoDB
 
Drupal, meet Assetic
Drupal, meet Assetic
Kris Wallsmith
 
RubyBarCamp “Полезные gems и plugins”
RubyBarCamp “Полезные gems и plugins”
apostlion
 
Python Developer's Daily Routine
Python Developer's Daily Routine
Maxim Avanov
 
Jquery Best Practices
Jquery Best Practices
brinsknaps
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Stripe
 
Kotlin: Let's Make Android Great Again
Kotlin: Let's Make Android Great Again
Taeho Kim
 
jQuery Namespace Pattern
jQuery Namespace Pattern
Diego Fleury
 
(안드로이드 개발자를 위한) 오픈소스 라이브러리 사용 가이드
(안드로이드 개발자를 위한) 오픈소스 라이브러리 사용 가이드
Taeho Kim
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
MongoDB
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
Jarod Ferguson
 
레진코믹스가 코틀린으로 간 까닭은?
레진코믹스가 코틀린으로 간 까닭은?
Taeho Kim
 
Delivering a Responsive UI
Delivering a Responsive UI
Rebecca Murphey
 
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Puppet
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
MongoDB
 
RubyBarCamp “Полезные gems и plugins”
RubyBarCamp “Полезные gems и plugins”
apostlion
 

Similar to FrontendLab: Programming UI with FRP and Bacon js - Вячеслав Ворончук (20)

jQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journey
Huiyi Yan
 
jQuery: Events, Animation, Ajax
jQuery: Events, Animation, Ajax
Constantin Titarenko
 
You will learn RxJS in 2017
You will learn RxJS in 2017
名辰 洪
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Domenic Denicola
 
Javascript And J Query
Javascript And J Query
itsarsalan
 
Advanced jQuery
Advanced jQuery
sergioafp
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)
Calvin Cheng
 
EcmaScript 6
EcmaScript 6
Manoj Kumar
 
Miracle of std lib
Miracle of std lib
Jedsada Tiwongvokul
 
Async data pipelines for client-side JavaScript
Async data pipelines for client-side JavaScript
Ismael Celis
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
Loïc Knuchel
 
Functionality Focused Code Organization
Functionality Focused Code Organization
Rebecca Murphey
 
Call stack, event loop and async programming
Call stack, event loop and async programming
Masters Academy
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is here
Sebastiano Armeli
 
Building Evented Single Page Applications
Building Evented Single Page Applications
Steve Smith
 
Building evented single page applications
Building evented single page applications
Steve Smith
 
JQuery Flot
JQuery Flot
Arshavski Alexander
 
Javascript
Javascript
Vlad Ifrim
 
Kick start with j query
Kick start with j query
Md. Ziaul Haq
 
関数潮流(Function Tendency)
関数潮流(Function Tendency)
riue
 
jQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journey
Huiyi Yan
 
You will learn RxJS in 2017
You will learn RxJS in 2017
名辰 洪
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Domenic Denicola
 
Javascript And J Query
Javascript And J Query
itsarsalan
 
Advanced jQuery
Advanced jQuery
sergioafp
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)
Calvin Cheng
 
Async data pipelines for client-side JavaScript
Async data pipelines for client-side JavaScript
Ismael Celis
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
Loïc Knuchel
 
Functionality Focused Code Organization
Functionality Focused Code Organization
Rebecca Murphey
 
Call stack, event loop and async programming
Call stack, event loop and async programming
Masters Academy
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is here
Sebastiano Armeli
 
Building Evented Single Page Applications
Building Evented Single Page Applications
Steve Smith
 
Building evented single page applications
Building evented single page applications
Steve Smith
 
Kick start with j query
Kick start with j query
Md. Ziaul Haq
 
関数潮流(Function Tendency)
関数潮流(Function Tendency)
riue
 
Ad

More from GeeksLab Odessa (20)

DataScience Lab2017_Коррекция геометрических искажений оптических спутниковых...
DataScience Lab2017_Коррекция геометрических искажений оптических спутниковых...
GeeksLab Odessa
 
DataScience Lab 2017_Kappa Architecture: How to implement a real-time streami...
DataScience Lab 2017_Kappa Architecture: How to implement a real-time streami...
GeeksLab Odessa
 
DataScience Lab 2017_Блиц-доклад_Турский Виктор
DataScience Lab 2017_Блиц-доклад_Турский Виктор
GeeksLab Odessa
 
DataScience Lab 2017_Обзор методов детекции лиц на изображение
DataScience Lab 2017_Обзор методов детекции лиц на изображение
GeeksLab Odessa
 
DataScienceLab2017_Сходство пациентов: вычистка дубликатов и предсказание про...
DataScienceLab2017_Сходство пациентов: вычистка дубликатов и предсказание про...
GeeksLab Odessa
 
DataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-доклад
GeeksLab Odessa
 
DataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-доклад
GeeksLab Odessa
 
DataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-доклад
GeeksLab Odessa
 
DataScienceLab2017_Cервинг моделей, построенных на больших данных с помощью A...
DataScienceLab2017_Cервинг моделей, построенных на больших данных с помощью A...
GeeksLab Odessa
 
DataScienceLab2017_BioVec: Word2Vec в задачах анализа геномных данных и биоин...
DataScienceLab2017_BioVec: Word2Vec в задачах анализа геномных данных и биоин...
GeeksLab Odessa
 
DataScienceLab2017_Data Sciences и Big Data в Телекоме_Александр Саенко
DataScienceLab2017_Data Sciences и Big Data в Телекоме_Александр Саенко
GeeksLab Odessa
 
DataScienceLab2017_Высокопроизводительные вычислительные возможности для сист...
DataScienceLab2017_Высокопроизводительные вычислительные возможности для сист...
GeeksLab Odessa
 
DataScience Lab 2017_Мониторинг модных трендов с помощью глубокого обучения и...
DataScience Lab 2017_Мониторинг модных трендов с помощью глубокого обучения и...
GeeksLab Odessa
 
DataScience Lab 2017_Кто здесь? Автоматическая разметка спикеров на телефонны...
DataScience Lab 2017_Кто здесь? Автоматическая разметка спикеров на телефонны...
GeeksLab Odessa
 
DataScience Lab 2017_From bag of texts to bag of clusters_Терпиль Евгений / П...
DataScience Lab 2017_From bag of texts to bag of clusters_Терпиль Евгений / П...
GeeksLab Odessa
 
DataScience Lab 2017_Графические вероятностные модели для принятия решений в ...
DataScience Lab 2017_Графические вероятностные модели для принятия решений в ...
GeeksLab Odessa
 
DataScienceLab2017_Оптимизация гиперпараметров машинного обучения при помощи ...
DataScienceLab2017_Оптимизация гиперпараметров машинного обучения при помощи ...
GeeksLab Odessa
 
DataScienceLab2017_Как знать всё о покупателях (или почти всё)?_Дарина Перемот
DataScienceLab2017_Как знать всё о покупателях (или почти всё)?_Дарина Перемот
GeeksLab Odessa
 
JS Lab 2017_Mapbox GL: как работают современные интерактивные карты_Владимир ...
JS Lab 2017_Mapbox GL: как работают современные интерактивные карты_Владимир ...
GeeksLab Odessa
 
JS Lab2017_Под микроскопом: блеск и нищета микросервисов на node.js
JS Lab2017_Под микроскопом: блеск и нищета микросервисов на node.js
GeeksLab Odessa
 
DataScience Lab2017_Коррекция геометрических искажений оптических спутниковых...
DataScience Lab2017_Коррекция геометрических искажений оптических спутниковых...
GeeksLab Odessa
 
DataScience Lab 2017_Kappa Architecture: How to implement a real-time streami...
DataScience Lab 2017_Kappa Architecture: How to implement a real-time streami...
GeeksLab Odessa
 
DataScience Lab 2017_Блиц-доклад_Турский Виктор
DataScience Lab 2017_Блиц-доклад_Турский Виктор
GeeksLab Odessa
 
DataScience Lab 2017_Обзор методов детекции лиц на изображение
DataScience Lab 2017_Обзор методов детекции лиц на изображение
GeeksLab Odessa
 
DataScienceLab2017_Сходство пациентов: вычистка дубликатов и предсказание про...
DataScienceLab2017_Сходство пациентов: вычистка дубликатов и предсказание про...
GeeksLab Odessa
 
DataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-доклад
GeeksLab Odessa
 
DataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-доклад
GeeksLab Odessa
 
DataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-доклад
GeeksLab Odessa
 
DataScienceLab2017_Cервинг моделей, построенных на больших данных с помощью A...
DataScienceLab2017_Cервинг моделей, построенных на больших данных с помощью A...
GeeksLab Odessa
 
DataScienceLab2017_BioVec: Word2Vec в задачах анализа геномных данных и биоин...
DataScienceLab2017_BioVec: Word2Vec в задачах анализа геномных данных и биоин...
GeeksLab Odessa
 
DataScienceLab2017_Data Sciences и Big Data в Телекоме_Александр Саенко
DataScienceLab2017_Data Sciences и Big Data в Телекоме_Александр Саенко
GeeksLab Odessa
 
DataScienceLab2017_Высокопроизводительные вычислительные возможности для сист...
DataScienceLab2017_Высокопроизводительные вычислительные возможности для сист...
GeeksLab Odessa
 
DataScience Lab 2017_Мониторинг модных трендов с помощью глубокого обучения и...
DataScience Lab 2017_Мониторинг модных трендов с помощью глубокого обучения и...
GeeksLab Odessa
 
DataScience Lab 2017_Кто здесь? Автоматическая разметка спикеров на телефонны...
DataScience Lab 2017_Кто здесь? Автоматическая разметка спикеров на телефонны...
GeeksLab Odessa
 
DataScience Lab 2017_From bag of texts to bag of clusters_Терпиль Евгений / П...
DataScience Lab 2017_From bag of texts to bag of clusters_Терпиль Евгений / П...
GeeksLab Odessa
 
DataScience Lab 2017_Графические вероятностные модели для принятия решений в ...
DataScience Lab 2017_Графические вероятностные модели для принятия решений в ...
GeeksLab Odessa
 
DataScienceLab2017_Оптимизация гиперпараметров машинного обучения при помощи ...
DataScienceLab2017_Оптимизация гиперпараметров машинного обучения при помощи ...
GeeksLab Odessa
 
DataScienceLab2017_Как знать всё о покупателях (или почти всё)?_Дарина Перемот
DataScienceLab2017_Как знать всё о покупателях (или почти всё)?_Дарина Перемот
GeeksLab Odessa
 
JS Lab 2017_Mapbox GL: как работают современные интерактивные карты_Владимир ...
JS Lab 2017_Mapbox GL: как работают современные интерактивные карты_Владимир ...
GeeksLab Odessa
 
JS Lab2017_Под микроскопом: блеск и нищета микросервисов на node.js
JS Lab2017_Под микроскопом: блеск и нищета микросервисов на node.js
GeeksLab Odessa
 
Ad

Recently uploaded (20)

Securing Account Lifecycles in the Age of Deepfakes.pptx
Securing Account Lifecycles in the Age of Deepfakes.pptx
FIDO Alliance
 
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Safe Software
 
Security Tips for Enterprise Azure Solutions
Security Tips for Enterprise Azure Solutions
Michele Leroux Bustamante
 
The Future of Technology: 2025-2125 by Saikat Basu.pdf
The Future of Technology: 2025-2125 by Saikat Basu.pdf
Saikat Basu
 
Salesforce Summer '25 Release Frenchgathering.pptx.pdf
Salesforce Summer '25 Release Frenchgathering.pptx.pdf
yosra Saidani
 
Coordinated Disclosure for ML - What's Different and What's the Same.pdf
Coordinated Disclosure for ML - What's Different and What's the Same.pdf
Priyanka Aash
 
9-1-1 Addressing: End-to-End Automation Using FME
9-1-1 Addressing: End-to-End Automation Using FME
Safe Software
 
" How to survive with 1 billion vectors and not sell a kidney: our low-cost c...
" How to survive with 1 billion vectors and not sell a kidney: our low-cost c...
Fwdays
 
"How to survive Black Friday: preparing e-commerce for a peak season", Yurii ...
"How to survive Black Friday: preparing e-commerce for a peak season", Yurii ...
Fwdays
 
Wenn alles versagt - IBM Tape schützt, was zählt! Und besonders mit dem neust...
Wenn alles versagt - IBM Tape schützt, was zählt! Und besonders mit dem neust...
Josef Weingand
 
AI vs Human Writing: Can You Tell the Difference?
AI vs Human Writing: Can You Tell the Difference?
Shashi Sathyanarayana, Ph.D
 
EIS-Webinar-Engineering-Retail-Infrastructure-06-16-2025.pdf
EIS-Webinar-Engineering-Retail-Infrastructure-06-16-2025.pdf
Earley Information Science
 
The Future of Product Management in AI ERA.pdf
The Future of Product Management in AI ERA.pdf
Alyona Owens
 
From Manual to Auto Searching- FME in the Driver's Seat
From Manual to Auto Searching- FME in the Driver's Seat
Safe Software
 
WebdriverIO & JavaScript: The Perfect Duo for Web Automation
WebdriverIO & JavaScript: The Perfect Duo for Web Automation
digitaljignect
 
Lessons Learned from Developing Secure AI Workflows.pdf
Lessons Learned from Developing Secure AI Workflows.pdf
Priyanka Aash
 
Cyber Defense Matrix Workshop - RSA Conference
Cyber Defense Matrix Workshop - RSA Conference
Priyanka Aash
 
"Scaling in space and time with Temporal", Andriy Lupa.pdf
"Scaling in space and time with Temporal", Andriy Lupa.pdf
Fwdays
 
10 Key Challenges for AI within the EU Data Protection Framework.pdf
10 Key Challenges for AI within the EU Data Protection Framework.pdf
Priyanka Aash
 
Quantum AI Discoveries: Fractal Patterns Consciousness and Cyclical Universes
Quantum AI Discoveries: Fractal Patterns Consciousness and Cyclical Universes
Saikat Basu
 
Securing Account Lifecycles in the Age of Deepfakes.pptx
Securing Account Lifecycles in the Age of Deepfakes.pptx
FIDO Alliance
 
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Using the SQLExecutor for Data Quality Management: aka One man's love for the...
Safe Software
 
Security Tips for Enterprise Azure Solutions
Security Tips for Enterprise Azure Solutions
Michele Leroux Bustamante
 
The Future of Technology: 2025-2125 by Saikat Basu.pdf
The Future of Technology: 2025-2125 by Saikat Basu.pdf
Saikat Basu
 
Salesforce Summer '25 Release Frenchgathering.pptx.pdf
Salesforce Summer '25 Release Frenchgathering.pptx.pdf
yosra Saidani
 
Coordinated Disclosure for ML - What's Different and What's the Same.pdf
Coordinated Disclosure for ML - What's Different and What's the Same.pdf
Priyanka Aash
 
9-1-1 Addressing: End-to-End Automation Using FME
9-1-1 Addressing: End-to-End Automation Using FME
Safe Software
 
" How to survive with 1 billion vectors and not sell a kidney: our low-cost c...
" How to survive with 1 billion vectors and not sell a kidney: our low-cost c...
Fwdays
 
"How to survive Black Friday: preparing e-commerce for a peak season", Yurii ...
"How to survive Black Friday: preparing e-commerce for a peak season", Yurii ...
Fwdays
 
Wenn alles versagt - IBM Tape schützt, was zählt! Und besonders mit dem neust...
Wenn alles versagt - IBM Tape schützt, was zählt! Und besonders mit dem neust...
Josef Weingand
 
AI vs Human Writing: Can You Tell the Difference?
AI vs Human Writing: Can You Tell the Difference?
Shashi Sathyanarayana, Ph.D
 
EIS-Webinar-Engineering-Retail-Infrastructure-06-16-2025.pdf
EIS-Webinar-Engineering-Retail-Infrastructure-06-16-2025.pdf
Earley Information Science
 
The Future of Product Management in AI ERA.pdf
The Future of Product Management in AI ERA.pdf
Alyona Owens
 
From Manual to Auto Searching- FME in the Driver's Seat
From Manual to Auto Searching- FME in the Driver's Seat
Safe Software
 
WebdriverIO & JavaScript: The Perfect Duo for Web Automation
WebdriverIO & JavaScript: The Perfect Duo for Web Automation
digitaljignect
 
Lessons Learned from Developing Secure AI Workflows.pdf
Lessons Learned from Developing Secure AI Workflows.pdf
Priyanka Aash
 
Cyber Defense Matrix Workshop - RSA Conference
Cyber Defense Matrix Workshop - RSA Conference
Priyanka Aash
 
"Scaling in space and time with Temporal", Andriy Lupa.pdf
"Scaling in space and time with Temporal", Andriy Lupa.pdf
Fwdays
 
10 Key Challenges for AI within the EU Data Protection Framework.pdf
10 Key Challenges for AI within the EU Data Protection Framework.pdf
Priyanka Aash
 
Quantum AI Discoveries: Fractal Patterns Consciousness and Cyclical Universes
Quantum AI Discoveries: Fractal Patterns Consciousness and Cyclical Universes
Saikat Basu
 

FrontendLab: Programming UI with FRP and Bacon js - Вячеслав Ворончук

  • 1. Programming UI with FRP and Bacon.js Vyacheslav Voronchuk [email protected] Skype: voronhukvk http://ua.linkedin.com/in/voronchuk/
  • 2. What is FRP? l  Sources of data l  Events l  Side-effects l  Switching
  • 5. How it helps? l  Callback spaghetti l  Refactoring l  New features and tweaks
  • 6. FlatMap $.ajax({ url: “/items” }).done(function(items) { if(items.error) { return handleError(items.error); } $.each(items, function(item) { $.ajax({ url: “/item/” + item.id }).done(function(item) { if(item.error) { return handleError(item.error); } renderItem(item, function(itemEl) { itemEl.children('.delete').click(function() { $.ajax({ url: “/item/” + item.id, type: 'DELETE' }).done(function(response) { if(response.error) { return handleError(response.error); } itemEl.remove(); }); }); }); }); }); });
  • 7. FlatMap isError = function(serverResponse) { return typeof serverResponse.error !== 'undefined' } isNotError = function(serverResponse) { return !isError(serverResponse); } $allItems = Bacon.fromPromise($.ajax({ url: “/items” })); $errors = $allItems.filter(isError); $items = $allItems.filter(isNotError).flatMap(function (item) { return Bacon.fromPromise($.ajax({ url: “/item” + item.id })); }); $errors.merge($items.filter(isError)); $renderedItems = $items.filter(isNotError).flatMap(function(item) { return Bacon.fromCallback(renderItem, item); }); $renderedItemsDeleteClicks = $renderedItems.flatMap(function(renderedItem){ return Bacon.fromEventTarget(renderedItem.children('.delete'), 'click', function(event) { return renderedItem; }); }); $deleteItemRequest = $renderedItemsDeleteClicks.flatMap(function(renderedItem) { return Bacon.fromPromise($.ajax({ url: “/item” + renderedItem.data('id'), type: 'DELETE' })); }); $errors.merge($deleteItemRequest.filter(isError)); $errors.onValue(handleError); $deleteItemRequest.filter(isNotError).onValue('.remove');
  • 8. When and Combine isError = function(serverResponse) { return typeof serverResponse.error !== 'undefined' } isNotError = function(serverResponse) { return !isError(serverResponse); } $items = Bacon.fromPromise($.ajax({ url: “/items” })); $renderedItems = $items.filter(isNotError).flatMap(function(item) { return Bacon.fromCallback(renderItem, item); }); $quantity = $renderedItems.flatMap(function(element) { return Bacon.fromEventTarget($(element).children('.quantity'), 'change').map(function(event) { return [element, $(element).val()]; }); }); $price = $quantity.map(function(data) { return $(data[0]).data('price') * data[1]; }); $refreshClick = Bacon.fromEventTarget($('#refresh_cart'), 'change'); Bacon.when( [$refreshClick, $quantity, $price], function(event, data, price) { $(data[0]).children('.internal-price').text(price); $(data[0]).children('.price').text(price); }, [$quantity, $price], function(data, price) { $(data[0]).children('.internal-price').text(price); } );
  • 9. Bus var $deleteItem = new Bacon.Bus(); $deleteItem.plug(Bacon.fromEventTarget($('.delete'), 'click')); $deleteItem.map('.target.remove'); $deleteItem.push($('item1'));
  • 10. Bus var chopsticks = [new Bacon.Bus(), new Bacon.Bus(), new Bacon.Bus()] var hungry = [new Bacon.Bus(), new Bacon.Bus(), new Bacon.Bus()] var eat = function(i) { return function() { setTimeout(function() { chopsticks[i].push({}) chopsticks[(i+1) % 3].push({}) }, 1000); return 'philosopher ' + i + ' eating' } } var dining = Bacon.when( [hungry[0], chopsticks[0], chopsticks[1]], eat(0), [hungry[1], chopsticks[1], chopsticks[2]], eat(1), [hungry[2], chopsticks[2], chopsticks[0]], eat(2) ).log() // make all chopsticks initially available chopsticks[0].push({}); chopsticks[1].push({}); chopsticks[2].push({}) // make philosophers hungry in some way, in this case we just push to their bus for (var i = 0; i < 3; i++) { hungry[0].push({}); hungry[1].push({}); hungry[2].push({}) }
  • 11. Usage in Node.js getInvoiceStream = (id) -> Bacon.fromNodeCallback Invoice, 'findOne', id: id getInvoiceDataStream = ($invoice) -> $invoice.flatMap (invoice) -> Bacon.fromNodeCallback invoice, 'toDeepJSON' # Load Invoice and it's deps get: (req, res) -> $invoice = getInvoiceStream req.param 'id' $invoiceData = getInvoiceDataStream invoice $invoiceData.onValue _.bind(res.json, res) $errors = Bacon.mergeAll $invoice.errors(), $invoiceData.errors() $errors.onError _.bind(res.send, res, 500) # Generate PDF export pdf: (req, res) -> $invoice = getInvoiceStream req.param 'id' $invoiceData = getInvoiceDataStream $invoice $invoiceRender = $invoiceData.map renderInvoicePDF $invoiceRenderData = $invoiceRender.flatMap (pdf) -> Bacon.fromCallback pdf, 'output' $invoiceRenderData.onValue _.bind(res.end, res) $errors = Bacon.mergeAll $invoice.errors(), $invoiceData.errors() $errors.onError _.bind(res.send, res, 500)
  • 12. AJAX Search // Stream of search queries var $query = $("#search").asEventStream("keyup").map(function(event) { return $(event.srcElement).val(); }).skipDuplicates(); // Search result strings var $results = $query.throttle(500).flatMapLatest(function(query) { return Bacon.fromPromise($.ajax("/search/" + query)) }).mapError("Search error"); // Render results $results.onValue(function(result) { $("#results").html(result); }); // Search status var searchStatus = $query.map(true).merge($results.map(false)).skipDuplicates().toProperty(false);
  • 15. Links l  Github page: https://github.com/baconjs/bacon.js l  Bacon.js blog: http://baconjs.blogspot.fi/ l  Snake game: http://philipnilsson.github.io/badness/ l  Worzone game: http://juhajasatu.com/worzone/