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

Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfhans926745
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 

Recently uploaded (20)

Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 

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/