SlideShare a Scribd company logo
Practical Functional
     JavaScript
         Oliver Steele
       Ajax Experience
   Wednesday, 1 October 2008
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
About Me
                                                      implementing           using
        where?                   what?            graphics languages   graphics languages


                        Ruby bindings for ā€œMinority
  Oblong Industries
                         Reportā€-style interfaces                        āœ”        āœ”
                               BrowseGoods
  Entrepreneurial &             Style&Share
     Consulting                   Fansnap                                āœ”        āœ”
                              Webtop Calendar


   Laszlo Systems           OpenLaszlo                        āœ”          āœ”

   Apple Advanced                Dylan                        āœ”          āœ”
  Technology Group       (programming language)

Apple System Software             Skia                āœ”                  āœ”
                             (graphics library)
About You
    Raise your hand if you know*:
    ā€¢    Closures
    ā€¢    Ruby / Smalltalk
    ā€¢    XHR / AJAX
    ā€¢    An AJAX framework (Prototype / jQuery / ā€¦)
    ā€¢    Threads



*   none of these are required; this just helps me calibrate the talk
Agenda
ā€¢   Context                     ā€¢   Callbacks
    ā€¢   Example Applications        ā€¢   Queueing & Throttling

    ā€¢   MVC on the Client           ā€¢   Caching & Joining

                                    ā€¢   Retries & Failover
ā€¢   Fundamentals
    ā€¢   Closures (review)       ā€¢   Conclusions
    ā€¢   Making Functions

    ā€¢   Decorating Functions
                                ā€¢   Q&A

    ā€¢   Some Idioms
Non-Agenda

    ā€¢ Comet, Bayeux, Gears
    ā€¢ Frameworks*
    ā€¢ Theory (this isn't your Monad or CPS ļ¬x)
    ā€¢ Security (standard practices apply)
*   This talk should help you understand their implementation and use, but doesn't explore
    their APIs in any depth
Example Applications
BrowseGoods
ā€¢   Visually browse an
    Amazon department,
    graphically arranged

ā€¢   Server: Ruby (layout,
    image processing, app
    server)

ā€¢   Client: Prototype +
    Scriptaculous
BrowseGoods
         Capabilities

ā€¢ Background prefetch of item maps
ā€¢ Background fetch of saved items
ā€¢ Operations on saved items are queued until
  initialization is complete
Style & Share                                                                                      Server Architecture
                                                                                                             Client



                                                                                                           Internet



                                                                                                   Web Application Processes

                                                                                       Catalog             Cart            Image
                                                                                      Controller         Controller       Controller


                                                                                       Catalog
                                                                                        Model




                                                                 Product                                                                   Image
                                                                 Request               Catalog             Carts           Images         Request
                                                                  Queue                                                                    Queue




                                                                  Catalog
                                                                                                                                        Image Editor
                                                                  Updater
                                                                                                       Cart Sweeper
                                                                                                                                          Image
                                                                ECS Client
                                                                                                                                         Retriever

                                                             Catalog Update Process                  Garbage Collector                 Image Process
                 Client Architecture

                                                                                                              Internet
  Catalog
                       Cart Manager
  Search                                          Gallery
                ECS Cart       Server Cart        Selector
 ECS Search                                                                               Amazon ECS                  Amazon Image
                 Proxy           Proxy                                                      Server                      Servers

      ECS Connection                     Server Proxy


       AJAX Throttle

      Task Scheduler



                         Internet



        ECS Server                    Style&Share Server
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
Fansnap
ā€¢   Visualize available seats
    in a venue

ā€¢   Seatmap is OpenLaszlo
    (compiled to Flash)

ā€¢   Widgets are in jQuery
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
Webtop Calendar
                                        Webtop Calendar Client Data Architecture


        Calendar Client




                                                   View Layer




                                                                                      Event
                          Event Model       Calendar Model
                                                                                     Observer




           Data Layer
                            Event               Calendar                   Calendar Service
                            Cache               Collection



                                                  Range               Event Report
                                                  Cache                  Cache



                        Serializer                        CalendarConnection




                                              Webtop Client Library




                                                    Internet




                                                Webtop Server
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
Motivating Problem:
    Web MVC
Server                        Client


                   View                          View


         Model                         Model                User



                 Controller                    Controller
MVC Basics
Server:
Waiting on the Client
    Server                               Client


                       View


             Model                User



                     Controller
Client:
Waiting on the Server
    Server                                Client


                               View


             Model   Model



                             Controller
Client:
Waiting on the User
                          Client


               View


     Model                         User



             Controller
Lots of Waiting
ā€¢   Client (server session)

ā€¢   Server (XHR)              ā€¢   Concurrency

ā€¢   User (UI event)           ā€¢   State

ā€¢   Future (setTimeout)
Function Fundamentals
What is a Function?        Create
                       Call graph


         ā€¢ Math: rule that maps inputs to outputs
                                                        Invoke
             Docs




         ā€¢ Computer science: abstracted computation
Specs        with effects and outputs
         ā€¢     Source                Runtime
             Software engineering: one of several units
                                                                    Register



             forCode                  Object
                 documentation, testing, assertions, and
 Defā€™n
             analysis
         ā€¢    Source code: unit of source text with              Store


              inputs and outputs
             Contract
                     Implementation

         ā€¢ Runtime: invocable parameterized behavior
                                                 Pass
Nested Functions:
         Globals
function callback(x) {
    log('received quot;' + x + 'quot;');
}
Ā 
function request() {
    $.get('/request', callback);
}
Ā 
request();
Ā 
Ā 
Nested Functions:
         Variables
var callback = function(x) {
    log('received quot;' + x + 'quot;');
}
Ā 
var request = function() {
    $.get('/request', callback);
}
Ā 
request();
Ā 
Ā 
Nested Functions:
    Function-First Style
function request() {
    function callback(x) {
        log('received quot;' + x + 'quot;');
    }
    $.get('/request', callback);
}
Ā 
request();
Ā 
Ā 
Nested Functions:
      Pyramid Order
function request() {
    $.get('/request', callback);
    function callback(x) {
        log('received quot;' + x + 'quot;');
    }
}
Ā 
request();
Ā 
Ā 
Nested Functions:
   Inlining the Function
function request() {
    $.get('/request', function callback(x) {
        log('received quot;' + x + 'quot;');
    });
}
Ā 
request();
Ā 
Ā 
Nested Functions:
       Anonymous
function request() {
    $.get('/request', function (x) {
        log('received quot;' + x + 'quot;');
    });
}
Ā 
request();
Ā 
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()());
Ā 
Ā 
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));
Ā 
Ā 
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));
Ā 
Ā 
Ā 
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));
Ā 
Ā 
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));
Ā 
Ā 
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));
Ā 
Ā 
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);
Ā 
Ā 
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);
Ā 
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());
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());
Ā 
Function Construction Idioms:
       Special Variables
// 'this' and 'arguments' are special
function f() {
    logArguments(this, arguments);
}
f();
f('a');
f('a', 'b');
Ā 
Ā 
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]);
Ā 
Ā 
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]);
Function Construction Idioms:
  Borrowing Methods (Bad)

// stealing a method the wrong way
var o1 = {name: 'o1',
          show: function() { log(this.name); }};
var o2 = {name: 'o2'};
o1.show();
o2.show = o1.show;
o2.show();
delete o2.show;
Ā 
Ā 
Function Construction Idioms:
 Borrowing Methods (Better)

// using 'apply' to steal a method
var o1 = {name: 'o1',
          show: function() { log(this.name); }};
var o2 = {name: 'o2'};
o1.show();
o1.show.call(o2);
o1.show.apply(o2, []);
Ā 
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 prototype
function capture() {
    var args = Array.prototype.slice.call(arguments, 0);
    // ...
}Ā 
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);
    }
}
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();
Function Construction Idioms:
Extending Functionā€™s Prototype
Function.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));
Ā 
Summary
ā€¢ Functions are values
 ā€¢ Functions can be arguments, return
    values, array elements, property values
 ā€¢ Functions can be created and ā€œmodiļ¬edā€
ā€¢ Argument lists can be saved, modiļ¬ed, and
  replayed
Case Study: Callbacks
      Server              Client

         <%@page
         <html>
           <?= t
           <meta




         <canvas
           <text
           <view




         <?xml v
         <%@ tag
         <xslt:t
         XML       <?xml
                   <root>
                     <row>
                     </row>




                   <?xml
                   <root>
                     <row>
                     </row>




         <?xml v
         <%@ tag
         XML
         <xslt:t
                   <?xml
                   <root>
                     <row>
                     </row>
Callback Scenarii
ā€¢   Chained Callbacks     ā€¢   Conjunctive-Trigger
                              Callbacks
ā€¢   Queues and Priority
                          ā€¢   Conditional Callbacks
ā€¢   Throttling
                          ā€¢   Outdated Responses
ā€¢   Caching

ā€¢   Timeouts

ā€¢   Retry and Failover
Throttling:
             Unthrottled
for (var i = 0; i < 10; i++)
    $.get('/services/time', log);
Ā 
Ā 
Frequency Throttling:
        Call Site
var gCounter = 0;
function runNext() {
    if (gCounter < 10) {
        setTimeout(function() {
            $.get('/services/time', log);
            runNext();
        }, 1000);
        gCounter++;
    }
}
runNext();
Ā 
Ā 
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);
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);
Ā 
Ā 
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);
Ā 
Ā 
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);
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);
Ā 
Ā 
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);
Ā 
Ā 
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);
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);
Ā 
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);
Ā 
Ā 
Caching (2)
var gPendingRequests = {};
var gRequestCache = {};                      $.cachedGet('/services/random',   log);
$.cachedGet = function(url, k) {             $.cachedGet('/services/random',   log);
    if (url in gRequestCache)                $.cachedGet('/services/echo/1',   log);
                                             $.cachedGet('/services/echo/2',   log);
        k(gRequestCache[url], 'success');
                                             $.cachedGet('/services/random',   log);
    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];
        });
    }
};Ā 
Caching (3)
function memoizedContinuation(fn) {
                                                    $.cachedGet('/services/random',   log);
    var cache = {};
    return function(key, k) {                       $.cachedGet('/services/random',   log);
        if (key in cache)                           $.cachedGet('/services/echo/1',   log);
            k(cache[key]);                          $.cachedGet('/services/echo/2',   log);
        else                                        $.cachedGet('/services/random',   log);
            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));
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
What is FP?


ā€¢ Functions are pure
ā€¢ Functions are values
Q&A
Thanks!




          ā€“ Oliver Steele
      http://osteele.com

More Related Content

What's hot

(ATS3-GS02) Accelrys Enterprise Platform in Enterprise Architectures
(ATS3-GS02) Accelrys Enterprise Platform in Enterprise Architectures(ATS3-GS02) Accelrys Enterprise Platform in Enterprise Architectures
(ATS3-GS02) Accelrys Enterprise Platform in Enterprise Architectures
BIOVIA
Ā 
Sakai Technical (Chinese)
Sakai Technical (Chinese)Sakai Technical (Chinese)
Sakai Technical (Chinese)jiali zhang
Ā 
Crx 2.2 Deep-Dive
Crx 2.2 Deep-DiveCrx 2.2 Deep-Dive
Crx 2.2 Deep-Dive
Gabriel Walt
Ā 
SQLUG event: An evening in the cloud: the old, the new and the big
 SQLUG event: An evening in the cloud: the old, the new and the big  SQLUG event: An evening in the cloud: the old, the new and the big
SQLUG event: An evening in the cloud: the old, the new and the big
Mike Martin
Ā 
Confoo2013 make your java-app rest enabled
Confoo2013 make your java-app rest enabledConfoo2013 make your java-app rest enabled
Confoo2013 make your java-app rest enabledAnthony Dahanne
Ā 
Social Photos - My presentation at Microsoft Tech Day
Social Photos - My presentation at Microsoft Tech DaySocial Photos - My presentation at Microsoft Tech Day
Social Photos - My presentation at Microsoft Tech Day
TechMaster Vietnam
Ā 
Composing Domain-Specific Languages
Composing Domain-Specific LanguagesComposing Domain-Specific Languages
Composing Domain-Specific Languages
Eelco Visser
Ā 
JAX 2012: Moderne Architektur mit Spring und JavaScript
JAX 2012: Moderne Architektur mit Spring und JavaScriptJAX 2012: Moderne Architektur mit Spring und JavaScript
JAX 2012: Moderne Architektur mit Spring und JavaScriptmartinlippert
Ā 
JavaOne 2009 - Full-Text Search: Human Heaven and Database Savior in the Cloud
JavaOne 2009 - Full-Text Search: Human Heaven and Database Savior in the CloudJavaOne 2009 - Full-Text Search: Human Heaven and Database Savior in the Cloud
JavaOne 2009 - Full-Text Search: Human Heaven and Database Savior in the CloudAaron Walker
Ā 
Expendables E-AppStore
Expendables E-AppStoreExpendables E-AppStore
Expendables E-AppStorelobalint
Ā 
Ajax World Fall08
Ajax World Fall08Ajax World Fall08
Ajax World Fall08rajivmordani
Ā 
JavaFX Versus HTML5 - JavaOne 2014
JavaFX Versus HTML5 - JavaOne 2014JavaFX Versus HTML5 - JavaOne 2014
JavaFX Versus HTML5 - JavaOne 2014
Ryan Cuprak
Ā 
Spring 3 - An Introduction
Spring 3 - An IntroductionSpring 3 - An Introduction
Spring 3 - An Introduction
Thorsten Kamann
Ā 
20100604 unyoug apex40_bauser
20100604 unyoug apex40_bauser20100604 unyoug apex40_bauser
20100604 unyoug apex40_bauserahmed farouk
Ā 
Java EE 8 Recipes
Java EE 8 RecipesJava EE 8 Recipes
Java EE 8 Recipes
Josh Juneau
Ā 
(ATS4-DEV04) Protocols as RESTful Services and RESTful URL Routing
(ATS4-DEV04) Protocols as RESTful Services and RESTful URL Routing(ATS4-DEV04) Protocols as RESTful Services and RESTful URL Routing
(ATS4-DEV04) Protocols as RESTful Services and RESTful URL Routing
BIOVIA
Ā 
Introducing WebLogic 12c OTN Tour 2012
Introducing WebLogic 12c OTN Tour 2012Introducing WebLogic 12c OTN Tour 2012
Introducing WebLogic 12c OTN Tour 2012
Bruno Borges
Ā 
Krishnakumar Rajendran (1)
Krishnakumar Rajendran (1)Krishnakumar Rajendran (1)
Krishnakumar Rajendran (1)Krishna Rajendran
Ā 
Content-Driven Web Applications with Magnolia CMS and Ruby on Rails
Content-Driven Web Applications with Magnolia CMS and Ruby on RailsContent-Driven Web Applications with Magnolia CMS and Ruby on Rails
Content-Driven Web Applications with Magnolia CMS and Ruby on Rails
bkraft
Ā 

What's hot (19)

(ATS3-GS02) Accelrys Enterprise Platform in Enterprise Architectures
(ATS3-GS02) Accelrys Enterprise Platform in Enterprise Architectures(ATS3-GS02) Accelrys Enterprise Platform in Enterprise Architectures
(ATS3-GS02) Accelrys Enterprise Platform in Enterprise Architectures
Ā 
Sakai Technical (Chinese)
Sakai Technical (Chinese)Sakai Technical (Chinese)
Sakai Technical (Chinese)
Ā 
Crx 2.2 Deep-Dive
Crx 2.2 Deep-DiveCrx 2.2 Deep-Dive
Crx 2.2 Deep-Dive
Ā 
SQLUG event: An evening in the cloud: the old, the new and the big
 SQLUG event: An evening in the cloud: the old, the new and the big  SQLUG event: An evening in the cloud: the old, the new and the big
SQLUG event: An evening in the cloud: the old, the new and the big
Ā 
Confoo2013 make your java-app rest enabled
Confoo2013 make your java-app rest enabledConfoo2013 make your java-app rest enabled
Confoo2013 make your java-app rest enabled
Ā 
Social Photos - My presentation at Microsoft Tech Day
Social Photos - My presentation at Microsoft Tech DaySocial Photos - My presentation at Microsoft Tech Day
Social Photos - My presentation at Microsoft Tech Day
Ā 
Composing Domain-Specific Languages
Composing Domain-Specific LanguagesComposing Domain-Specific Languages
Composing Domain-Specific Languages
Ā 
JAX 2012: Moderne Architektur mit Spring und JavaScript
JAX 2012: Moderne Architektur mit Spring und JavaScriptJAX 2012: Moderne Architektur mit Spring und JavaScript
JAX 2012: Moderne Architektur mit Spring und JavaScript
Ā 
JavaOne 2009 - Full-Text Search: Human Heaven and Database Savior in the Cloud
JavaOne 2009 - Full-Text Search: Human Heaven and Database Savior in the CloudJavaOne 2009 - Full-Text Search: Human Heaven and Database Savior in the Cloud
JavaOne 2009 - Full-Text Search: Human Heaven and Database Savior in the Cloud
Ā 
Expendables E-AppStore
Expendables E-AppStoreExpendables E-AppStore
Expendables E-AppStore
Ā 
Ajax World Fall08
Ajax World Fall08Ajax World Fall08
Ajax World Fall08
Ā 
JavaFX Versus HTML5 - JavaOne 2014
JavaFX Versus HTML5 - JavaOne 2014JavaFX Versus HTML5 - JavaOne 2014
JavaFX Versus HTML5 - JavaOne 2014
Ā 
Spring 3 - An Introduction
Spring 3 - An IntroductionSpring 3 - An Introduction
Spring 3 - An Introduction
Ā 
20100604 unyoug apex40_bauser
20100604 unyoug apex40_bauser20100604 unyoug apex40_bauser
20100604 unyoug apex40_bauser
Ā 
Java EE 8 Recipes
Java EE 8 RecipesJava EE 8 Recipes
Java EE 8 Recipes
Ā 
(ATS4-DEV04) Protocols as RESTful Services and RESTful URL Routing
(ATS4-DEV04) Protocols as RESTful Services and RESTful URL Routing(ATS4-DEV04) Protocols as RESTful Services and RESTful URL Routing
(ATS4-DEV04) Protocols as RESTful Services and RESTful URL Routing
Ā 
Introducing WebLogic 12c OTN Tour 2012
Introducing WebLogic 12c OTN Tour 2012Introducing WebLogic 12c OTN Tour 2012
Introducing WebLogic 12c OTN Tour 2012
Ā 
Krishnakumar Rajendran (1)
Krishnakumar Rajendran (1)Krishnakumar Rajendran (1)
Krishnakumar Rajendran (1)
Ā 
Content-Driven Web Applications with Magnolia CMS and Ruby on Rails
Content-Driven Web Applications with Magnolia CMS and Ruby on RailsContent-Driven Web Applications with Magnolia CMS and Ruby on Rails
Content-Driven Web Applications with Magnolia CMS and Ruby on Rails
Ā 

Similar to Practical Functional Javascript

Practical functional java script
Practical functional java scriptPractical functional java script
Practical functional java script
thinkphp
Ā 
(ATS3-APP14) Troubleshooting Symyx Notebook client performance
(ATS3-APP14) Troubleshooting Symyx Notebook client performance(ATS3-APP14) Troubleshooting Symyx Notebook client performance
(ATS3-APP14) Troubleshooting Symyx Notebook client performance
BIOVIA
Ā 
(ATS4-GS02) A Lap Around Accelrys Enterprise Platform and Pipeline Pilot 9.0
(ATS4-GS02) A Lap Around Accelrys Enterprise Platform and Pipeline Pilot 9.0(ATS4-GS02) A Lap Around Accelrys Enterprise Platform and Pipeline Pilot 9.0
(ATS4-GS02) A Lap Around Accelrys Enterprise Platform and Pipeline Pilot 9.0
BIOVIA
Ā 
Āµjax in 30 minutes (for Stockholm)
Āµjax in 30 minutes (for Stockholm)Āµjax in 30 minutes (for Stockholm)
Āµjax in 30 minutes (for Stockholm)
guestf67bc2
Ā 
Āµjax in 30 minutes (for Stockholm)
Āµjax in 30 minutes (for Stockholm)Āµjax in 30 minutes (for Stockholm)
Āµjax in 30 minutes (for Stockholm)
Lars Trieloff
Ā 
Āµjax in 30 minutes
Āµjax in 30 minutesĀµjax in 30 minutes
Āµjax in 30 minutes
Lars Trieloff
Ā 
Advanced Silverlight
Advanced SilverlightAdvanced Silverlight
Advanced Silverlightrsnarayanan
Ā 
vert.x - asynchronous event-driven web applications on the JVM
vert.x - asynchronous event-driven web applications on the JVMvert.x - asynchronous event-driven web applications on the JVM
vert.x - asynchronous event-driven web applications on the JVM
jbandi
Ā 
Mesh-Enabled Web Applications
Mesh-Enabled Web ApplicationsMesh-Enabled Web Applications
Mesh-Enabled Web Applications
goodfriday
Ā 
CloudStack Collaboration Conference 12; Refactoring cloud stack
CloudStack Collaboration Conference 12; Refactoring cloud stackCloudStack Collaboration Conference 12; Refactoring cloud stack
CloudStack Collaboration Conference 12; Refactoring cloud stack
buildacloud
Ā 
Operating the Hyperscale Cloud
Operating the Hyperscale CloudOperating the Hyperscale Cloud
Operating the Hyperscale CloudOpen Stack
Ā 
Balconies, Patios, Terraces, and Bridges. Architectural approaches for moving...
Balconies, Patios, Terraces, and Bridges. Architectural approaches for moving...Balconies, Patios, Terraces, and Bridges. Architectural approaches for moving...
Balconies, Patios, Terraces, and Bridges. Architectural approaches for moving...
mfrancis
Ā 
Deep dive ECS & Fargate Deep Dive
Deep dive ECS & Fargate Deep DiveDeep dive ECS & Fargate Deep Dive
Deep dive ECS & Fargate Deep Dive
Amazon Web Services
Ā 
(ATS3-GS03) Accelrys Enterprise Platform Deeper Dive
(ATS3-GS03) Accelrys Enterprise Platform Deeper Dive(ATS3-GS03) Accelrys Enterprise Platform Deeper Dive
(ATS3-GS03) Accelrys Enterprise Platform Deeper Dive
BIOVIA
Ā 
Plugin-able POS Solutions by Javascript @HDM9 Taiwan
Plugin-able POS Solutions by Javascript @HDM9 TaiwanPlugin-able POS Solutions by Javascript @HDM9 Taiwan
Plugin-able POS Solutions by Javascript @HDM9 Taiwan
Rack Lin
Ā 
Wpf Tech Overview2009
Wpf Tech Overview2009Wpf Tech Overview2009
Wpf Tech Overview2009
Our Community Exchange LLC
Ā 
2011 07-27 ecoop innovation network
2011 07-27 ecoop innovation network2011 07-27 ecoop innovation network
2011 07-27 ecoop innovation network
ruzannaChitchyan
Ā 
InduSoft VBScript Webinar
 InduSoft VBScript Webinar InduSoft VBScript Webinar
InduSoft VBScript WebinarAVEVA
Ā 
SPEC INDIA Java Case Study
SPEC INDIA Java Case StudySPEC INDIA Java Case Study
SPEC INDIA Java Case StudySPEC INDIA
Ā 
Visibility into Serverless Applications built using AWS Fargate (CON312-R1) -...
Visibility into Serverless Applications built using AWS Fargate (CON312-R1) -...Visibility into Serverless Applications built using AWS Fargate (CON312-R1) -...
Visibility into Serverless Applications built using AWS Fargate (CON312-R1) -...
Amazon Web Services
Ā 

Similar to Practical Functional Javascript (20)

Practical functional java script
Practical functional java scriptPractical functional java script
Practical functional java script
Ā 
(ATS3-APP14) Troubleshooting Symyx Notebook client performance
(ATS3-APP14) Troubleshooting Symyx Notebook client performance(ATS3-APP14) Troubleshooting Symyx Notebook client performance
(ATS3-APP14) Troubleshooting Symyx Notebook client performance
Ā 
(ATS4-GS02) A Lap Around Accelrys Enterprise Platform and Pipeline Pilot 9.0
(ATS4-GS02) A Lap Around Accelrys Enterprise Platform and Pipeline Pilot 9.0(ATS4-GS02) A Lap Around Accelrys Enterprise Platform and Pipeline Pilot 9.0
(ATS4-GS02) A Lap Around Accelrys Enterprise Platform and Pipeline Pilot 9.0
Ā 
Āµjax in 30 minutes (for Stockholm)
Āµjax in 30 minutes (for Stockholm)Āµjax in 30 minutes (for Stockholm)
Āµjax in 30 minutes (for Stockholm)
Ā 
Āµjax in 30 minutes (for Stockholm)
Āµjax in 30 minutes (for Stockholm)Āµjax in 30 minutes (for Stockholm)
Āµjax in 30 minutes (for Stockholm)
Ā 
Āµjax in 30 minutes
Āµjax in 30 minutesĀµjax in 30 minutes
Āµjax in 30 minutes
Ā 
Advanced Silverlight
Advanced SilverlightAdvanced Silverlight
Advanced Silverlight
Ā 
vert.x - asynchronous event-driven web applications on the JVM
vert.x - asynchronous event-driven web applications on the JVMvert.x - asynchronous event-driven web applications on the JVM
vert.x - asynchronous event-driven web applications on the JVM
Ā 
Mesh-Enabled Web Applications
Mesh-Enabled Web ApplicationsMesh-Enabled Web Applications
Mesh-Enabled Web Applications
Ā 
CloudStack Collaboration Conference 12; Refactoring cloud stack
CloudStack Collaboration Conference 12; Refactoring cloud stackCloudStack Collaboration Conference 12; Refactoring cloud stack
CloudStack Collaboration Conference 12; Refactoring cloud stack
Ā 
Operating the Hyperscale Cloud
Operating the Hyperscale CloudOperating the Hyperscale Cloud
Operating the Hyperscale Cloud
Ā 
Balconies, Patios, Terraces, and Bridges. Architectural approaches for moving...
Balconies, Patios, Terraces, and Bridges. Architectural approaches for moving...Balconies, Patios, Terraces, and Bridges. Architectural approaches for moving...
Balconies, Patios, Terraces, and Bridges. Architectural approaches for moving...
Ā 
Deep dive ECS & Fargate Deep Dive
Deep dive ECS & Fargate Deep DiveDeep dive ECS & Fargate Deep Dive
Deep dive ECS & Fargate Deep Dive
Ā 
(ATS3-GS03) Accelrys Enterprise Platform Deeper Dive
(ATS3-GS03) Accelrys Enterprise Platform Deeper Dive(ATS3-GS03) Accelrys Enterprise Platform Deeper Dive
(ATS3-GS03) Accelrys Enterprise Platform Deeper Dive
Ā 
Plugin-able POS Solutions by Javascript @HDM9 Taiwan
Plugin-able POS Solutions by Javascript @HDM9 TaiwanPlugin-able POS Solutions by Javascript @HDM9 Taiwan
Plugin-able POS Solutions by Javascript @HDM9 Taiwan
Ā 
Wpf Tech Overview2009
Wpf Tech Overview2009Wpf Tech Overview2009
Wpf Tech Overview2009
Ā 
2011 07-27 ecoop innovation network
2011 07-27 ecoop innovation network2011 07-27 ecoop innovation network
2011 07-27 ecoop innovation network
Ā 
InduSoft VBScript Webinar
 InduSoft VBScript Webinar InduSoft VBScript Webinar
InduSoft VBScript Webinar
Ā 
SPEC INDIA Java Case Study
SPEC INDIA Java Case StudySPEC INDIA Java Case Study
SPEC INDIA Java Case Study
Ā 
Visibility into Serverless Applications built using AWS Fargate (CON312-R1) -...
Visibility into Serverless Applications built using AWS Fargate (CON312-R1) -...Visibility into Serverless Applications built using AWS Fargate (CON312-R1) -...
Visibility into Serverless Applications built using AWS Fargate (CON312-R1) -...
Ā 

Recently uploaded

PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
Ā 
The Metaverse and AI: how can decision-makers harness the Metaverse for their...
The Metaverse and AI: how can decision-makers harness the Metaverse for their...The Metaverse and AI: how can decision-makers harness the Metaverse for their...
The Metaverse and AI: how can decision-makers harness the Metaverse for their...
Jen Stirrup
Ā 
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptxSecstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
nkrafacyberclub
Ā 
Dev Dives: Train smarter, not harder ā€“ active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder ā€“ active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder ā€“ active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder ā€“ active learning and UiPath LLMs for do...
UiPathCommunity
Ā 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
Ā 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
Ā 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
DanBrown980551
Ā 
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilotā„¢
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilotā„¢Le nuove frontiere dell'AI nell'RPA con UiPath Autopilotā„¢
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilotā„¢
UiPathCommunity
Ā 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
Ā 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Nexer Digital
Ā 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
Ā 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-UniversitƤt
Ā 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
Ā 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Kari Kakkonen
Ā 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
Ā 
Quantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIsQuantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIs
Vlad Stirbu
Ā 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
Ā 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
Alex Pruden
Ā 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
Ā 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
Ā 

Recently uploaded (20)

PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
Ā 
The Metaverse and AI: how can decision-makers harness the Metaverse for their...
The Metaverse and AI: how can decision-makers harness the Metaverse for their...The Metaverse and AI: how can decision-makers harness the Metaverse for their...
The Metaverse and AI: how can decision-makers harness the Metaverse for their...
Ā 
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptxSecstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Ā 
Dev Dives: Train smarter, not harder ā€“ active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder ā€“ active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder ā€“ active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder ā€“ active learning and UiPath LLMs for do...
Ā 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
Ā 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
Ā 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
Ā 
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilotā„¢
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilotā„¢Le nuove frontiere dell'AI nell'RPA con UiPath Autopilotā„¢
Le nuove frontiere dell'AI nell'RPA con UiPath Autopilotā„¢
Ā 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
Ā 
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?Elizabeth Buie - Older adults: Are we really designing for our future selves?
Elizabeth Buie - Older adults: Are we really designing for our future selves?
Ā 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Ā 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Ā 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
Ā 
DevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA ConnectDevOps and Testing slides at DASA Connect
DevOps and Testing slides at DASA Connect
Ā 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
Ā 
Quantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIsQuantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIs
Ā 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ā 
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex ProofszkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
zkStudyClub - Reef: Fast Succinct Non-Interactive Zero-Knowledge Regex Proofs
Ā 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Ā 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Ā 

Practical Functional Javascript

  • 1. Practical Functional JavaScript Oliver Steele Ajax Experience Wednesday, 1 October 2008
  • 2. 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
  • 3. About Me implementing using where? what? graphics languages graphics languages Ruby bindings for ā€œMinority Oblong Industries Reportā€-style interfaces āœ” āœ” BrowseGoods Entrepreneurial & Style&Share Consulting Fansnap āœ” āœ” Webtop Calendar Laszlo Systems OpenLaszlo āœ” āœ” Apple Advanced Dylan āœ” āœ” Technology Group (programming language) Apple System Software Skia āœ” āœ” (graphics library)
  • 4. About You Raise your hand if you know*: ā€¢ Closures ā€¢ Ruby / Smalltalk ā€¢ XHR / AJAX ā€¢ An AJAX framework (Prototype / jQuery / ā€¦) ā€¢ Threads * none of these are required; this just helps me calibrate the talk
  • 5. Agenda ā€¢ Context ā€¢ Callbacks ā€¢ Example Applications ā€¢ Queueing & Throttling ā€¢ MVC on the Client ā€¢ Caching & Joining ā€¢ Retries & Failover ā€¢ Fundamentals ā€¢ Closures (review) ā€¢ Conclusions ā€¢ Making Functions ā€¢ Decorating Functions ā€¢ Q&A ā€¢ Some Idioms
  • 6. Non-Agenda ā€¢ Comet, Bayeux, Gears ā€¢ Frameworks* ā€¢ Theory (this isn't your Monad or CPS ļ¬x) ā€¢ Security (standard practices apply) * This talk should help you understand their implementation and use, but doesn't explore their APIs in any depth
  • 8. BrowseGoods ā€¢ Visually browse an Amazon department, graphically arranged ā€¢ Server: Ruby (layout, image processing, app server) ā€¢ Client: Prototype + Scriptaculous
  • 9.
  • 10. BrowseGoods Capabilities ā€¢ Background prefetch of item maps ā€¢ Background fetch of saved items ā€¢ Operations on saved items are queued until initialization is complete
  • 11. Style & Share Server Architecture Client Internet Web Application Processes Catalog Cart Image Controller Controller Controller Catalog Model Product Image Request Catalog Carts Images Request Queue Queue Catalog Image Editor Updater Cart Sweeper Image ECS Client Retriever Catalog Update Process Garbage Collector Image Process Client Architecture Internet Catalog Cart Manager Search Gallery ECS Cart Server Cart Selector ECS Search Amazon ECS Amazon Image Proxy Proxy Server Servers ECS Connection Server Proxy AJAX Throttle Task Scheduler Internet ECS Server Style&Share Server
  • 12.
  • 13. 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
  • 14. Fansnap ā€¢ Visualize available seats in a venue ā€¢ Seatmap is OpenLaszlo (compiled to Flash) ā€¢ Widgets are in jQuery
  • 15.
  • 16. 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
  • 17. Webtop Calendar Webtop Calendar Client Data Architecture Calendar Client View Layer Event Event Model Calendar Model Observer Data Layer Event Calendar Calendar Service Cache Collection Range Event Report Cache Cache Serializer CalendarConnection Webtop Client Library Internet Webtop Server
  • 18.
  • 19. 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
  • 20. Motivating Problem: Web MVC Server Client View View Model Model User Controller Controller
  • 22. Server: Waiting on the Client Server Client View Model User Controller
  • 23. Client: Waiting on the Server Server Client View Model Model Controller
  • 24. Client: Waiting on the User Client View Model User Controller
  • 25. Lots of Waiting ā€¢ Client (server session) ā€¢ Server (XHR) ā€¢ Concurrency ā€¢ User (UI event) ā€¢ State ā€¢ Future (setTimeout)
  • 27. What is a Function? Create Call graph ā€¢ Math: rule that maps inputs to outputs Invoke Docs ā€¢ Computer science: abstracted computation Specs with effects and outputs ā€¢ Source Runtime Software engineering: one of several units Register forCode Object documentation, testing, assertions, and Defā€™n analysis ā€¢ Source code: unit of source text with Store inputs and outputs Contract Implementation ā€¢ Runtime: invocable parameterized behavior Pass
  • 28. Nested Functions: Globals function callback(x) { log('received quot;' + x + 'quot;'); } Ā  function request() { $.get('/request', callback); } Ā  request(); Ā  Ā 
  • 29. Nested Functions: Variables var callback = function(x) { log('received quot;' + x + 'quot;'); } Ā  var request = function() { $.get('/request', callback); } Ā  request(); Ā  Ā 
  • 30. Nested Functions: Function-First Style function request() { function callback(x) { log('received quot;' + x + 'quot;'); } $.get('/request', callback); } Ā  request(); Ā  Ā 
  • 31. Nested Functions: Pyramid Order function request() { $.get('/request', callback); function callback(x) { log('received quot;' + x + 'quot;'); } } Ā  request(); Ā  Ā 
  • 32. Nested Functions: Inlining the Function function request() { $.get('/request', function callback(x) { log('received quot;' + x + 'quot;'); }); } Ā  request(); Ā  Ā 
  • 33. Nested Functions: Anonymous function request() { $.get('/request', function (x) { log('received quot;' + x + 'quot;'); }); } Ā  request(); Ā 
  • 34. 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()()); Ā  Ā 
  • 35. 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)); Ā  Ā 
  • 36. 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)); Ā  Ā  Ā 
  • 37. 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)); Ā  Ā 
  • 38. 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)); Ā  Ā 
  • 39. 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)); Ā  Ā 
  • 40. 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); Ā  Ā 
  • 41. 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); Ā 
  • 42. 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());
  • 43. 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()); Ā 
  • 44. Function Construction Idioms: Special Variables // 'this' and 'arguments' are special function f() { logArguments(this, arguments); } f(); f('a'); f('a', 'b'); Ā  Ā 
  • 45. 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]); Ā  Ā 
  • 46. 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]);
  • 47. Function Construction Idioms: Borrowing Methods (Bad) // stealing a method the wrong way var o1 = {name: 'o1', show: function() { log(this.name); }}; var o2 = {name: 'o2'}; o1.show(); o2.show = o1.show; o2.show(); delete o2.show; Ā  Ā 
  • 48. Function Construction Idioms: Borrowing Methods (Better) // using 'apply' to steal a method var o1 = {name: 'o1', show: function() { log(this.name); }}; var o2 = {name: 'o2'}; o1.show(); o1.show.call(o2); o1.show.apply(o2, []); Ā 
  • 49. 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 prototype function capture() { var args = Array.prototype.slice.call(arguments, 0); // ... }Ā 
  • 50. 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); } }
  • 51. 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();
  • 52. Function Construction Idioms: Extending Functionā€™s Prototype Function.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)); Ā 
  • 53. Summary ā€¢ Functions are values ā€¢ Functions can be arguments, return values, array elements, property values ā€¢ Functions can be created and ā€œmodiļ¬edā€ ā€¢ Argument lists can be saved, modiļ¬ed, and replayed
  • 54. Case Study: Callbacks Server Client <%@page <html> <?= t <meta <canvas <text <view <?xml v <%@ tag <xslt:t XML <?xml <root> <row> </row> <?xml <root> <row> </row> <?xml v <%@ tag XML <xslt:t <?xml <root> <row> </row>
  • 55. Callback Scenarii ā€¢ Chained Callbacks ā€¢ Conjunctive-Trigger Callbacks ā€¢ Queues and Priority ā€¢ Conditional Callbacks ā€¢ Throttling ā€¢ Outdated Responses ā€¢ Caching ā€¢ Timeouts ā€¢ Retry and Failover
  • 56. Throttling: Unthrottled for (var i = 0; i < 10; i++) $.get('/services/time', log); Ā  Ā 
  • 57. Frequency Throttling: Call Site var gCounter = 0; function runNext() { if (gCounter < 10) { setTimeout(function() { $.get('/services/time', log); runNext(); }, 1000); gCounter++; } } runNext(); Ā  Ā 
  • 58. 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);
  • 59. 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); Ā  Ā 
  • 60. 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); Ā  Ā 
  • 61. 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);
  • 62. 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); Ā  Ā 
  • 63. 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); Ā  Ā 
  • 64. 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);
  • 65. 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); Ā 
  • 66. 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); Ā  Ā 
  • 67. Caching (2) var gPendingRequests = {}; var gRequestCache = {}; $.cachedGet('/services/random', log); $.cachedGet = function(url, k) { $.cachedGet('/services/random', log); if (url in gRequestCache) $.cachedGet('/services/echo/1', log); $.cachedGet('/services/echo/2', log); k(gRequestCache[url], 'success'); $.cachedGet('/services/random', log); 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]; }); } };Ā 
  • 68. Caching (3) function memoizedContinuation(fn) { $.cachedGet('/services/random', log); var cache = {}; return function(key, k) { $.cachedGet('/services/random', log); if (key in cache) $.cachedGet('/services/echo/1', log); k(cache[key]); $.cachedGet('/services/echo/2', log); else $.cachedGet('/services/random', log); 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));
  • 69. 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
  • 70. What is FP? ā€¢ Functions are pure ā€¢ Functions are values
  • 71. Q&A
  • 72. Thanks! ā€“ Oliver Steele http://osteele.com