SlideShare ist ein Scribd-Unternehmen logo
1 von 72
Downloaden Sie, um offline zu lesen
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 fix)
    • 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 “modified”
• Argument lists can be saved, modified, 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

Weitere ähnliche Inhalte

Was ist angesagt?

(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 ArchitecturesBIOVIA
 
Sakai Technical (Chinese)
Sakai Technical (Chinese)Sakai Technical (Chinese)
Sakai Technical (Chinese)jiali zhang
 
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 DayTechMaster Vietnam
 
Composing Domain-Specific Languages
Composing Domain-Specific LanguagesComposing Domain-Specific Languages
Composing Domain-Specific LanguagesEelco 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
 
JavaFX Versus HTML5 - JavaOne 2014
JavaFX Versus HTML5 - JavaOne 2014JavaFX Versus HTML5 - JavaOne 2014
JavaFX Versus HTML5 - JavaOne 2014Ryan Cuprak
 
Spring 3 - An Introduction
Spring 3 - An IntroductionSpring 3 - An Introduction
Spring 3 - An IntroductionThorsten 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 RecipesJosh 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 RoutingBIOVIA
 
Introducing WebLogic 12c OTN Tour 2012
Introducing WebLogic 12c OTN Tour 2012Introducing WebLogic 12c OTN Tour 2012
Introducing WebLogic 12c OTN Tour 2012Bruno Borges
 
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 Railsbkraft
 

Was ist angesagt? (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
 

Ähnlich wie Practical Functional Javascript

Practical functional java script
Practical functional java scriptPractical functional java script
Practical functional java scriptthinkphp
 
(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 performanceBIOVIA
 
(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.0BIOVIA
 
µ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
 
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 JVMjbandi
 
Mesh-Enabled Web Applications
Mesh-Enabled Web ApplicationsMesh-Enabled Web Applications
Mesh-Enabled Web Applicationsgoodfriday
 
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 stackbuildacloud
 
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 DiveAmazon 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 DiveBIOVIA
 
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 TaiwanRack Lin
 
2011 07-27 ecoop innovation network
2011 07-27 ecoop innovation network2011 07-27 ecoop innovation network
2011 07-27 ecoop innovation networkruzannaChitchyan
 
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
 

Ähnlich wie 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) -...
 

Kürzlich hochgeladen

New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesZilliz
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 

Kürzlich hochgeladen (20)

New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Vector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector DatabasesVector Databases 101 - An introduction to the world of Vector Databases
Vector Databases 101 - An introduction to the world of Vector Databases
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 

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 fix) • 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 “modified” • Argument lists can be saved, modified, 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