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

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

Sources of data

●

Events

●

Side-effects

●

Switching
Javascript FRP frameworks
●

Elm

●

Flapjax

●

Javelin

●

RxJS

●

others
How it helps?
●

Callback spaghetti

●

Refactoring

●

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
●

Observable.log()

●

Observable.toString()

●

Observable.deps()

●

Observable.internalDeps()

●

Bacon.spy(f)
Notices
●

onValue

●

fromArray
Links
●

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

●

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

●

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

●

Worzone game: http://juhajasatu.com/worzone/
FRP and Bacon.js

More Related Content

What's hot

JavaScript APIs - The Web is the Platform - MDN Hack Day - Buenos Aires
JavaScript APIs - The Web is the Platform - MDN Hack Day - Buenos AiresJavaScript APIs - The Web is the Platform - MDN Hack Day - Buenos Aires
JavaScript APIs - The Web is the Platform - MDN Hack Day - Buenos AiresRobert Nyman
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Tsuyoshi Yamamoto
 
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、GaelykでハンズオンTsuyoshi Yamamoto
 
Beyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS AppsBeyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS AppsRebecca Murphey
 
Let's Build A Gutenberg Block | WordCamp Europe 2018
Let's Build A Gutenberg Block | WordCamp Europe 2018Let's Build A Gutenberg Block | WordCamp Europe 2018
Let's Build A Gutenberg Block | WordCamp Europe 2018Lara Schenck
 
Delivering a Responsive UI
Delivering a Responsive UIDelivering a Responsive UI
Delivering a Responsive UIRebecca Murphey
 
Nodejs do teste de unidade ao de integração
Nodejs  do teste de unidade ao de integraçãoNodejs  do teste de unidade ao de integração
Nodejs do teste de unidade ao de integraçãoVinícius Pretto da Silva
 
Building Single Page Apps with Backbone.js, Coffeescript and Rails 3.1
Building Single Page Apps with Backbone.js, Coffeescript and Rails 3.1Building Single Page Apps with Backbone.js, Coffeescript and Rails 3.1
Building Single Page Apps with Backbone.js, Coffeescript and Rails 3.1Vagmi Mudumbai
 
jQuery Namespace Pattern
jQuery Namespace PatternjQuery Namespace Pattern
jQuery Namespace PatternDiego Fleury
 
Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察Tsuyoshi Yamamoto
 
Jqeury ajax plugins
Jqeury ajax pluginsJqeury ajax plugins
Jqeury ajax pluginsInbal Geffen
 
Jquery Best Practices
Jquery Best PracticesJquery Best Practices
Jquery Best Practicesbrinsknaps
 
Super Advanced Python –act1
Super Advanced Python –act1Super Advanced Python –act1
Super Advanced Python –act1Ke Wei Louis
 
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014Puppet
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsJarod Ferguson
 
Python Developer's Daily Routine
Python Developer's Daily RoutinePython Developer's Daily Routine
Python Developer's Daily RoutineMaxim Avanov
 

What's hot (20)

JavaScript APIs - The Web is the Platform - MDN Hack Day - Buenos Aires
JavaScript APIs - The Web is the Platform - MDN Hack Day - Buenos AiresJavaScript APIs - The Web is the Platform - MDN Hack Day - Buenos Aires
JavaScript APIs - The Web is the Platform - MDN Hack Day - Buenos Aires
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
 
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
名古屋SGGAE/J勉強会 Grails、Gaelykでハンズオン
 
Beyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS AppsBeyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS Apps
 
Let's Build A Gutenberg Block | WordCamp Europe 2018
Let's Build A Gutenberg Block | WordCamp Europe 2018Let's Build A Gutenberg Block | WordCamp Europe 2018
Let's Build A Gutenberg Block | WordCamp Europe 2018
 
Jquery Fundamentals
Jquery FundamentalsJquery Fundamentals
Jquery Fundamentals
 
Everyday's JS
Everyday's JSEveryday's JS
Everyday's JS
 
BVJS
BVJSBVJS
BVJS
 
Delivering a Responsive UI
Delivering a Responsive UIDelivering a Responsive UI
Delivering a Responsive UI
 
Nodejs do teste de unidade ao de integração
Nodejs  do teste de unidade ao de integraçãoNodejs  do teste de unidade ao de integração
Nodejs do teste de unidade ao de integração
 
Building Single Page Apps with Backbone.js, Coffeescript and Rails 3.1
Building Single Page Apps with Backbone.js, Coffeescript and Rails 3.1Building Single Page Apps with Backbone.js, Coffeescript and Rails 3.1
Building Single Page Apps with Backbone.js, Coffeescript and Rails 3.1
 
jQuery Namespace Pattern
jQuery Namespace PatternjQuery Namespace Pattern
jQuery Namespace Pattern
 
Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察
 
Gaelyk
GaelykGaelyk
Gaelyk
 
Jqeury ajax plugins
Jqeury ajax pluginsJqeury ajax plugins
Jqeury ajax plugins
 
Jquery Best Practices
Jquery Best PracticesJquery Best Practices
Jquery Best Practices
 
Super Advanced Python –act1
Super Advanced Python –act1Super Advanced Python –act1
Super Advanced Python –act1
 
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
 
Python Developer's Daily Routine
Python Developer's Daily RoutinePython Developer's Daily Routine
Python Developer's Daily Routine
 

Viewers also liked

Laboring - защити свои права!
Laboring - защити свои права!Laboring - защити свои права!
Laboring - защити свои права!Роман Савчук
 
Эндогенное дыхание - книга
Эндогенное дыхание - книгаЭндогенное дыхание - книга
Эндогенное дыхание - книгаПётр Буянов
 
Coffeescript a z
Coffeescript a zCoffeescript a z
Coffeescript a zStarbuildr
 
Meteor modules
Meteor modulesMeteor modules
Meteor modulesStarbuildr
 
Как стать профессиональным дайвером в море информации
Как стать профессиональным дайвером в море информацииКак стать профессиональным дайвером в море информации
Как стать профессиональным дайвером в море информацииРоман Савчук
 
Информация и правила работы с ней.
Информация и правила работы с ней.Информация и правила работы с ней.
Информация и правила работы с ней.Роман Савчук
 
презентация ДО ПриCутствия
презентация ДО ПриCутствия презентация ДО ПриCутствия
презентация ДО ПриCутствия Пётр Буянов
 
Odoo 2016 - Retrospective
Odoo 2016 - RetrospectiveOdoo 2016 - Retrospective
Odoo 2016 - RetrospectiveOdoo
 

Viewers also liked (12)

Laboring - защити свои права!
Laboring - защити свои права!Laboring - защити свои права!
Laboring - защити свои права!
 
Эндогенное дыхание - книга
Эндогенное дыхание - книгаЭндогенное дыхание - книга
Эндогенное дыхание - книга
 
Coffeescript a z
Coffeescript a zCoffeescript a z
Coffeescript a z
 
Явление Иерархии
Явление ИерархииЯвление Иерархии
Явление Иерархии
 
Meteor modules
Meteor modulesMeteor modules
Meteor modules
 
Как стать профессиональным дайвером в море информации
Как стать профессиональным дайвером в море информацииКак стать профессиональным дайвером в море информации
Как стать профессиональным дайвером в море информации
 
Inter capital en
Inter capital enInter capital en
Inter capital en
 
Информация и правила работы с ней.
Информация и правила работы с ней.Информация и правила работы с ней.
Информация и правила работы с ней.
 
презентация ДО ПриCутствия
презентация ДО ПриCутствия презентация ДО ПриCутствия
презентация ДО ПриCутствия
 
Prez f
Prez fPrez f
Prez f
 
жителям мд
жителям мджителям мд
жителям мд
 
Odoo 2016 - Retrospective
Odoo 2016 - RetrospectiveOdoo 2016 - Retrospective
Odoo 2016 - Retrospective
 

Similar to FRP and Bacon.js

jQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journeyjQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journeyHuiyi Yan
 
You will learn RxJS in 2017
You will learn RxJS in 2017You 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...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Domenic Denicola
 
Call stack, event loop and async programming
Call stack, event loop and async programmingCall stack, event loop and async programming
Call stack, event loop and async programmingMasters Academy
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuerysergioafp
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Calvin Cheng
 
Javascript And J Query
Javascript And J QueryJavascript And J Query
Javascript And J Queryitsarsalan
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptLoïc Knuchel
 
Building evented single page applications
Building evented single page applicationsBuilding evented single page applications
Building evented single page applicationsSteve Smith
 
Building Evented Single Page Applications
Building Evented Single Page ApplicationsBuilding Evented Single Page Applications
Building Evented Single Page ApplicationsSteve Smith
 
Async data pipelines for client-side JavaScript
Async data pipelines for client-side JavaScriptAsync data pipelines for client-side JavaScript
Async data pipelines for client-side JavaScriptIsmael Celis
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs偉格 高
 
Functionality Focused Code Organization
Functionality Focused Code OrganizationFunctionality Focused Code Organization
Functionality Focused Code OrganizationRebecca Murphey
 
The Strange World of Javascript and all its little Asynchronous Beasts
The Strange World of Javascript and all its little Asynchronous BeastsThe Strange World of Javascript and all its little Asynchronous Beasts
The Strange World of Javascript and all its little Asynchronous BeastsFederico Galassi
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is hereSebastiano Armeli
 
Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)jeffz
 

Similar to FRP and Bacon.js (20)

jQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journeyjQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journey
 
You will learn RxJS in 2017
You will learn RxJS in 2017You will learn RxJS in 2017
You will learn RxJS in 2017
 
jQuery: Events, Animation, Ajax
jQuery: Events, Animation, AjaxjQuery: Events, Animation, Ajax
jQuery: Events, Animation, Ajax
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
Call stack, event loop and async programming
Call stack, event loop and async programmingCall stack, event loop and async programming
Call stack, event loop and async programming
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuery
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)
 
EcmaScript 6
EcmaScript 6 EcmaScript 6
EcmaScript 6
 
Javascript And J Query
Javascript And J QueryJavascript And J Query
Javascript And J Query
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
 
Building evented single page applications
Building evented single page applicationsBuilding evented single page applications
Building evented single page applications
 
Building Evented Single Page Applications
Building Evented Single Page ApplicationsBuilding Evented Single Page Applications
Building Evented Single Page Applications
 
Async data pipelines for client-side JavaScript
Async data pipelines for client-side JavaScriptAsync data pipelines for client-side JavaScript
Async data pipelines for client-side JavaScript
 
Functional programming using underscorejs
Functional programming using underscorejsFunctional programming using underscorejs
Functional programming using underscorejs
 
Functionality Focused Code Organization
Functionality Focused Code OrganizationFunctionality Focused Code Organization
Functionality Focused Code Organization
 
Javascript
JavascriptJavascript
Javascript
 
The Strange World of Javascript and all its little Asynchronous Beasts
The Strange World of Javascript and all its little Asynchronous BeastsThe Strange World of Javascript and all its little Asynchronous Beasts
The Strange World of Javascript and all its little Asynchronous Beasts
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is here
 
Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)Jscex: Write Sexy JavaScript (中文)
Jscex: Write Sexy JavaScript (中文)
 
ES6 Overview
ES6 OverviewES6 Overview
ES6 Overview
 

Recently uploaded

Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 

Recently uploaded (20)

Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort ServiceHot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 

FRP and Bacon.js

  • 1. Programming UI with FRP and Bacon.js Vyacheslav Voronchuk voronchuk@wm-software.com Skype: voronhukvk http://ua.linkedin.com/in/voronchuk/
  • 2. What is FRP? ● Sources of data ● Events ● Side-effects ● Switching
  • 4.
  • 5. How it helps? ● Callback spaghetti ● Refactoring ● 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 ● Github page: https://github.com/baconjs/bacon.js ● Bacon.js blog: http://baconjs.blogspot.fi/ ● Snake game: http://philipnilsson.github.io/badness/ ● Worzone game: http://juhajasatu.com/worzone/