practical functional java script
DESCRIPTION
Practical Functional JavaScriptTRANSCRIPT
![Page 1: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/1.jpg)
Practical Functional JavaScript
Oliver SteeleAjax Experience
Wednesday, 1 October 2008
![Page 2: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/2.jpg)
Teasers
• AJAX is all about waiting for someone*, and remembering what you were going to do when they got back to you.
• Functions : interactions :: objects : domains
• You didn't really want threads anyway. (Most of the time.)
* user, web server, other server, wall clock, plugin
![Page 3: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/3.jpg)
About Mewhere? what? graphics languages
implementing usinggraphics languages
✔ ✔
✔ ✔
✔ ✔
✔ ✔
✔ ✔
Oblong IndustriesRuby bindings for “Minority
Report”-style interfaces
Entrepreneurial & Consulting
BrowseGoodsStyle&Share
FansnapWebtop Calendar
Laszlo Systems OpenLaszlo
Apple Advanced Technology Group
Dylan(programming language)
Apple System Software Skia(graphics library)
![Page 4: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/4.jpg)
About YouRaise your hand if you know*:
* none of these are required; this just helps me calibrate the talk
• Closures
• Ruby / Smalltalk
• XHR / AJAX
• An AJAX framework (Prototype / jQuery / …)
• Threads
![Page 5: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/5.jpg)
Agenda• Context
• Example Applications
• MVC on the Client
• Fundamentals
• Closures (review)
• Making Functions
• Decorating Functions
• Some Idioms
• Callbacks
• Queueing & Throttling
• Caching & Joining
• Retries & Failover
• Conclusions
• Q&A
![Page 6: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/6.jpg)
Non-Agenda
• Comet, Bayeux, Gears
• Frameworks*
• Theory (this isn't your Monad or CPS fix)
• Security (standard practices apply)
* This talk should help you understand their implementation and use, but doesn't explore their APIs in any depth
![Page 7: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/7.jpg)
Example Applications
![Page 8: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/8.jpg)
BrowseGoods• Visually browse an
Amazon department, graphically arranged
• Server: Ruby (layout, image processing, app server)
• Client: Prototype + Scriptaculous
![Page 9: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/9.jpg)
![Page 10: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/10.jpg)
BrowseGoods Capabilities
• Background prefetch of item maps
• Background fetch of saved items
• Operations on saved items are queued until initialization is complete
![Page 11: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/11.jpg)
Style & Share
Web Application Processes
Image ProcessGarbage Collector
Image Retriever
Catalog Update Process
Product Request Queue
Amazon ECS Server
Catalog Controller
Image Editor
Catalog Carts Images
Catalog Updater
ECS Client
Cart Controller
Image Controller
Image Request Queue
Cart Sweeper
Amazon Image Servers
Catalog Model
Internet
Client
Internet
Server Architecture
ECS Server
Catalog Search
Cart Manager
ECS Cart Proxy
ECS Connection
Server Cart Proxy
Style&Share Server
ECS Search
Gallery Selector
Server Proxy
Internet
AJAX Throttle
Task Scheduler
Client Architecture
![Page 12: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/12.jpg)
![Page 13: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/13.jpg)
Style & Share Capabilities
• Retry with exponential backoff and failover
• Explicit queues to control serialization order
• Background prefetch for catalog items
• Multiple queues to prioritize user interaction
![Page 14: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/14.jpg)
Fansnap• Visualize available seats
in a venue
• Seatmap is OpenLaszlo (compiled to Flash)
• Widgets are in jQuery
![Page 15: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/15.jpg)
![Page 16: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/16.jpg)
FanSnap Capabilities(Seatmap)
• Two-way asynchronous communication between the Flash plugin and the HTML
• Asynchronous communication between the Flash plugin and the server
• Again, initialization is particularly challenging
![Page 17: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/17.jpg)
Webtop Calendar
Da
ta L
ay
er
Calendar Client
Webtop Calendar Client Data Architecture
Range Cache
Calendar Model
Calendar ServiceCalendar Collection
EventObserver
View Layer
Event Cache
Serializer
Webtop Client Library
CalendarConnection
Event ReportCache
Webtop Server
Internet
Event Model
![Page 18: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/18.jpg)
![Page 19: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/19.jpg)
Webtop Calendar Capabilities (Data Model)
• Synchronizes local model with server model
• Local model is cache: some operations update it; others invalidate it
• Race conditions, where prefetch overlaps operations that invalidate the cache
![Page 20: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/20.jpg)
Motivating Problem:Web MVC
View
Controller
Model
Server
View
Controller
Model User
Client
![Page 21: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/21.jpg)
MVC Basics
![Page 22: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/22.jpg)
Server:Waiting on the Client
View
Controller
Model User
Server Client
![Page 23: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/23.jpg)
Client:Waiting on the Server
View
Controller
Model
Client
Model
Server
![Page 24: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/24.jpg)
Client:Waiting on the User
View
Controller
Model User
Client
![Page 25: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/25.jpg)
Lots of Waiting• Client (server session)
• Server (XHR)
• User (UI event)
• Future (setTimeout)
• Concurrency
• State
![Page 26: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/26.jpg)
Function Fundamentals
![Page 27: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/27.jpg)
What is a Function?• Math: rule that maps inputs to outputs
• Computer science: abstracted computation with effects and outputs
• Software engineering: one of several units for documentation, testing, assertions, and analysis
• Source code: unit of source text with inputs and outputs
• Runtime: invocable parameterized behavior
Source Code
Runtime Object
Docs
Specs
Def’n
ContractImplementation
Call graphCreate
Invoke
Register
Store
Pass
![Page 28: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/28.jpg)
Nested Functions: Globals
function callback(x) { log('received "' + x + '"');} function request() { $.get('/request', callback);} request();
![Page 29: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/29.jpg)
Nested Functions: Variables
var callback = function(x) { log('received "' + x + '"');} var request = function() { $.get('/request', callback);} request();
![Page 30: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/30.jpg)
Nested Functions: Function-First Style
function request() { function callback(x) { log('received "' + x + '"'); } $.get('/request', callback);} request();
![Page 31: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/31.jpg)
Nested Functions: Pyramid Order
function request() { $.get('/request', callback); function callback(x) { log('received "' + x + '"'); }} request();
![Page 32: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/32.jpg)
Nested Functions: Inlining the Function
function request() { $.get('/request', function callback(x) { log('received "' + x + '"'); });} request();
![Page 33: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/33.jpg)
Nested Functions: Anonymous
function request() { $.get('/request', function (x) { log('received "' + x + '"'); });} request();
![Page 34: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/34.jpg)
Creating Functions:Basics
function makeConst1() { return function() { return 1; }} function const1a() { return 1; }var const1b = function() { return 1; }var const1c = makeConst1(); log(const1a());log(const1b());log(const1c()); log(makeConst1()());
![Page 35: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/35.jpg)
Creating Functions: Variable Capture
function makeConstN(n) { return function() { return n; }} var const10 = makeConstN(10);log(const10());log(const10(100)); var const20 = makeConstN(20);log(const20());log(const20(100));
![Page 36: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/36.jpg)
Creating Functions: Capturing More Variables function makePlus1() { return function(x) { return x + 1; }}log(makePlus1()(10));
function makePlusN(n) { return function(x) { return x + n; }}var plus10 = makePlusN(10);log(plus10(100));
![Page 37: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/37.jpg)
Creating Functions: Function-Valued Parameters
function plus1(x) { return x+1;} function twice(fn) { return function(x) { return fn(fn(x)); }} var plus2 = twice(plus1);log(plus2(10));
![Page 38: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/38.jpg)
Creating Functions: Storage
var FnTable = { '+1': function(n) { return n+1; }, '+2': function(n) { return n+2; }}; log(FnTable['+1'](10));log(FnTable['+2'](10));
![Page 39: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/39.jpg)
Creating Functions: Building a Registry
var FnTable = {};function register(name, fn) { FnTable[name] = fn; }function tableMethod(name) { return FnTable[name]; }
function makeAdder(n) { return function(x) { return x + n; }} register('+1', makeAdder(1));register('+2', makeAdder(2));
log(tableMethod('+1')(10));log(tableMethod('+2')(10));
![Page 40: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/40.jpg)
Creating Functions: Manual Guards
for (var i = -5; i < 5; i++) log(i); function callIfPositive(fn) { return function(x) { return x > 0 ? fn(x) : undefined; }} var logIfPositive = callIfPositive(log); for (var i = -5; i < 5; i++) logIfPositive(i);
![Page 41: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/41.jpg)
Creating Functions: Guard Construction
function guard(fn, g) { return function(x) { return g(x) ? fn(x) : undefined; }} function callIfPositive(fn) { return guard(fn, function(x) { return x > 0; });} var logIfPositive = callIfPositive(log); for (var i = -5; i < 5; i++) logIfPositive(i);
![Page 42: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/42.jpg)
Closures (1)
var get, set;function assignAccessors() { var x = 1; get = function() { return x; } set = function(y) { x = y; }}
assignAccessors();log(get());set(10);log(get());
![Page 43: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/43.jpg)
Closures (2) function makeAccessors() { var x; return {get: function() { return x; }, set: function(y) { x = y; }}}
var gf1 = makeAccessors();var gf2 = makeAccessors();gf1.set(10);gf2.set(20);log(gf1.get());log(gf2.get());
![Page 44: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/44.jpg)
Function Construction Idioms:Special Variables
// 'this' and 'arguments' are specialfunction f() { logArguments(this, arguments);}f();f('a');f('a', 'b');
![Page 45: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/45.jpg)
Function Construction Idioms:Function Call and Apply
function f() { logArguments(this, arguments); }
// these are equivalent:f(1, 2, 3);f.call(window, 1, 2, 3);f.apply(window, [1, 2, 3]);
![Page 46: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/46.jpg)
Function Construction Idioms:Method Call and Apply
var obj = { f: function() { logArguments(this, arguments); }};
// and so are these:obj.f(1, 2, 3);obj.f.call(obj, 1, 2, 3);obj.f.apply(obj, [1, 2, 3]);
![Page 47: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/47.jpg)
Function Construction Idioms:Borrowing Methods (Bad)
// stealing a method the wrong wayvar o1 = {name: 'o1', show: function() { log(this.name); }};var o2 = {name: 'o2'};o1.show();o2.show = o1.show;o2.show();delete o2.show;
![Page 48: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/48.jpg)
Function Construction Idioms:Borrowing Methods (Better)
// using 'apply' to steal a methodvar o1 = {name: 'o1', show: function() { log(this.name); }};var o2 = {name: 'o2'};o1.show();o1.show.call(o2);o1.show.apply(o2, []);
![Page 49: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/49.jpg)
Function Construction Idioms:arguments is special
// arguments isn't an Array, so this doesn't work:function capture() { var args = arguments.slice(0); // ...} // instead, steal the 'slice' method from an instance of Array,// and apply it:function capture() { var args = [].slice.call(arguments, 0); // ...} // or just take it from Array's prototypefunction capture() { var args = Array.prototype.slice.call(arguments, 0); // ...}
![Page 50: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/50.jpg)
Function Construction Idioms:Wrapping Variadic Functions
function id1(fn) { return function(x) { return fn(x); }} function id2(fn) { return function(x, y) { return fn(x, y); }} function idn(fn) { return function() { return fn.apply(this, arguments); }}
![Page 51: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/51.jpg)
Function Construction Idioms:Record and Replay
var queue = [];function capture() { queue.push(Array.prototype.slice.call(arguments, 0));}function replay() { while (queue.length) fn.apply(null, queue.shift());}function fn(a, b) { log(a + ' + ' + b + ' = ' + (a+b));}capture(1,2);capture(1,3);capture(10,20);replay();
![Page 52: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/52.jpg)
Function Construction Idioms:Extending Function’s PrototypeFunction.prototype.twice = function() { var fn = this; return function() { return fn.call(this, fn.apply(this, arguments)); };}
function plus1(x) { return x+1; }var plus2 = plus1.twice();log(plus2(10));
![Page 53: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/53.jpg)
Summary
• Functions are values
• Functions can be arguments, return values, array elements, property values
• Functions can be created and “modified”
• Argument lists can be saved, modified, and replayed
![Page 54: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/54.jpg)
Case Study: CallbacksServer Client
<%@page
<html>
<?= t
<meta
<canvas
<text
<view
<?xml v
<%@ tag
<xslt:t<?xml
<root>
<row>
</row>
<?xml v
<%@ tag
<xslt:t
<?xml
<root>
<row>
</row>
<?xml
<root>
<row>
</row>
XML
XML
![Page 55: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/55.jpg)
Callback Scenarii• Chained Callbacks
• Queues and Priority
• Throttling
• Caching
• Timeouts
• Retry and Failover
• Conjunctive-Trigger Callbacks
• Conditional Callbacks
• Outdated Responses
![Page 56: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/56.jpg)
Throttling:Unthrottled
for (var i = 0; i < 10; i++) $.get('/services/time', log);
![Page 57: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/57.jpg)
Frequency Throttling:Call Site
var gCounter = 0;function runNext() { if (gCounter < 10) { setTimeout(function() { $.get('/services/time', log); runNext(); }, 1000); gCounter++; }}runNext();
![Page 58: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/58.jpg)
Frequency Throttling:Manual Wrapper
var gQueue = [];var gNextTime = 0;$.throttled = function(url, k) { gQueue.push([url, k]); if (gQueue.length == 1) schedule(); function schedule() { setTimeout(function() { gNextTime = new Date().getTime() + 1000; var entry = gQueue.shift(); $.get(entry[0], entry[1]); if (gQueue.length) schedule(); }, Math.max(0, gNextTime - new Date().getTime())); }};
for (var i = 0; i < 10; i++) $.throttled('/services/time', log);
![Page 59: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/59.jpg)
Frequency Throttling:Function Constructor
function makeThrottled(fn, interval) { var queue = []; var nextTime = 0; return function() { queue.push(Array.prototype.slice.call(arguments, 0)); if (queue.length == 1) schedule(); } function schedule() { setTimeout(function() { nextTime = new Date().getTime() + interval; fn.apply(null, queue.shift()); if (queue.length) schedule(); }, Math.max(0, nextTime - new Date().getTime())); }}
$.throttled = makeThrottled($.get, 1000);
for (var i = 0; i < 10; i++) $.throttled('/services/time', log);
![Page 60: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/60.jpg)
Count Throttling:Manual Wrapper
var gQueue = [];var gOutstanding = 0;$.throttled = function(url, k) { function k2() { gOutstanding--; k.apply(this, arguments); if (gOutstanding < 2 && gQueue.length) { var entry = gQueue.shift(); $.get(entry[0], entry[1]); } } if (gOutstanding < 2) { gOutstanding++; $.get(url, k2); } else gQueue.push([url, k2]);};
for (var i = 0; i < 10; i++) $.throttled('/services/sleep/2', log);
![Page 61: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/61.jpg)
Count Throttling:Constructor
function makeLimited(fn, count) { var queue = []; var outstanding = 0; return function() { var args = Array.prototype.slice.call(arguments, 0); // replace the last arg by one that runs the // next queued fn args.push(adviseAfter(args.pop(), next)); if (outstanding < count) { outstanding++; fn.apply(this, args); } else queue.push(args); } function next() { if (queue.length) fn.apply(null, queue.shift()); }}
$.throttled = makeLimited($.get, 2); for (var i = 0; i < 10; i++) $.throttled('/services/sleep/2', log);
![Page 62: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/62.jpg)
Frequency Throttling:Function Constructor
function makeThrottled(fn, interval) { var queue = []; var nextTime = 0; return function() { queue.push(Array.prototype.slice.call(arguments, 0)); if (queue.length == 1) schedule(); } function schedule() { setTimeout(function() { nextTime = new Date().getTime() + interval; fn.apply(null, queue.shift()); if (queue.length) schedule(); }, Math.max(0, nextTime - new Date().getTime())); }}
$.throttled = makeThrottled($.get, 1000);
for (var i = 0; i < 10; i++) $.throttled('/services/time', log);
![Page 63: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/63.jpg)
Retry$.getWithRetry = function(url, k) { var countdown = 10; $.ajax({url:url, success:k, error:retry}); function retry() { if (--countdown >= 0) { log('retry'); $.ajax({url:url, success:k, error:retry}); } }};
$.getWithRetry('/services/error', log);
![Page 64: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/64.jpg)
Throttled Retry var gPageLoadTime = new Date;$.getWithRetry = function(url, k) { var countdown = 10; var delay = 1000; var nextTime = new Date().getTime() + delay; $.ajax({url:url, success:k, error:retry}); function retry() { if (--countdown >= 0) { setTimeout(function() { delay *= 1.5; log('retry@t+' + (new Date - gPageLoadTime)/1000 + 's'); nextTime = new Date().getTime() + delay; $.ajax({url:url, success:k, error:retry}); }, Math.max(0, nextTime - new Date().getTime())); } }};
$.getWithRetry('/services/error', log);
![Page 65: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/65.jpg)
Failover
$.getWithFailover = function(urls, k) { $.ajax({url:urls.shift(), success:k, error:retry}); function retry() { if (urls.length) $.ajax({url:urls.shift(), success:k, error:retry}); }};
$.getWithFailover( ['/services/error', '/services/error', '/services/time'], log);
![Page 66: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/66.jpg)
Caching (1) var gRequestCache = {};$.cachedGet = function(url, k) { if (url in gRequestCache) k(gRequestCache[url], 'success'); else $.get(url, adviseBefore(k, function(result, status) { if (status == 'success') gRequestCache[url] = result; }));};
$.cachedGet('/services/random', log);$.cachedGet('/services/random', log);$.cachedGet('/services/echo/1', log);$.cachedGet('/services/echo/2', log);setTimeout(function() {$.cachedGet('/services/random', log);},
1000);
![Page 67: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/67.jpg)
Caching (2)
var gPendingRequests = {};var gRequestCache = {};$.cachedGet = function(url, k) { if (url in gRequestCache) k(gRequestCache[url], 'success'); else if (url in gPendingRequests) gPendingRequests[url].push(k); else { var queue = [k]; gPendingRequests[url] = queue; $.get(url, function(result, status) { if (status == 'success') gRequestCache[url] = result; while (queue.length) queue.shift().call(this, result, status); delete gPendingRequests[url]; }); }};
$.cachedGet('/services/random', log);$.cachedGet('/services/random', log);$.cachedGet('/services/echo/1', log);$.cachedGet('/services/echo/2', log);$.cachedGet('/services/random', log);
![Page 68: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/68.jpg)
Caching (3)function memoizedContinuation(fn) { var cache = {}; return function(key, k) { if (key in cache) k(cache[key]); else fn(key, k); }}function consolidateContinuations(fn) { var queues = {}; return function(key, k) { if (key in queues) queues[key].push(k); else { var queue = queues[key] = [k]; fn(key, function(value) { while (queue.length) queue.shift().call(this, value); delete queues[key]; }); } }}$.cachedGet = consolidateContinuations(memoizedContinuation($.get));
$.cachedGet('/services/random', log);$.cachedGet('/services/random', log);$.cachedGet('/services/echo/1', log);$.cachedGet('/services/echo/2', log);$.cachedGet('/services/random', log);
![Page 69: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/69.jpg)
Summary
• Functions-as-objects allow separation of concerns
• Factor how, when, and whether from what
• Functions are to interaction patterns as objects are to domains
![Page 70: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/70.jpg)
What is FP?
• Functions are pure
• Functions are values
![Page 71: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/71.jpg)
Q&A
![Page 72: Practical functional java script](https://reader034.vdocuments.net/reader034/viewer/2022050921/5542002e550346022e8b45bb/html5/thumbnails/72.jpg)
Thanks!
– Oliver Steele
http://osteele.com