SlideShare uma empresa Scribd logo
1 de 72
Baixar para ler offline
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 "' + x + '"');
}
 
function request() {
    $.get('/request', callback);
}
 
request();
 
 
Nested Functions:
         Variables
var callback = function(x) {
    log('received "' + x + '"');
}
 
var request = function() {
    $.get('/request', callback);
}
 
request();
 
 
Nested Functions:
    Function-First Style
function request() {
    function callback(x) {
        log('received "' + x + '"');
    }
    $.get('/request', callback);
}
 
request();
 
 
Nested Functions:
      Pyramid Order
function request() {
    $.get('/request', callback);
    function callback(x) {
        log('received "' + x + '"');
    }
}
 
request();
 
 
Nested Functions:
   Inlining the Function
function request() {
    $.get('/request', function callback(x) {
        log('received "' + x + '"');
    });
}
 
request();
 
 
Nested Functions:
       Anonymous
function request() {
    $.get('/request', function (x) {
        log('received "' + x + '"');
    });
}
 
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

Mais conteúdo relacionado

Semelhante a 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 performanceBIOVIA
 
Expendables E-AppStore
Expendables E-AppStoreExpendables E-AppStore
Expendables E-AppStorelobalint
 
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
 
(ATS4-APP09)Tips and tricks for Managing Symyx Notebook Server Performance
(ATS4-APP09)Tips and tricks for Managing Symyx Notebook Server Performance(ATS4-APP09)Tips and tricks for Managing Symyx Notebook Server Performance
(ATS4-APP09)Tips and tricks for Managing Symyx Notebook Server PerformanceBIOVIA
 
Operating the Hyperscale Cloud
Operating the Hyperscale CloudOperating the Hyperscale Cloud
Operating the Hyperscale CloudOpen Stack
 
SPEC INDIA Java Case Study
SPEC INDIA Java Case StudySPEC INDIA Java Case Study
SPEC INDIA Java Case StudySPEC INDIA
 
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
 
Build Java Web Application Using Apache Struts
Build Java Web Application Using Apache Struts Build Java Web Application Using Apache Struts
Build Java Web Application Using Apache Struts weili_at_slideshare
 
Sakai Technical Chinese
Sakai Technical ChineseSakai Technical Chinese
Sakai Technical Chinesejiali zhang
 
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
 
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
 
Summer training oracle
Summer training   oracle Summer training   oracle
Summer training oracle Arshit Rai
 
Backbonification for dummies - Arrrrug 10/1/2012
Backbonification for dummies - Arrrrug 10/1/2012Backbonification for dummies - Arrrrug 10/1/2012
Backbonification for dummies - Arrrrug 10/1/2012Dimitri de Putte
 
(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
 
(ATS4-PLAT05) Accelrys Catalog: A Search Index for AEP
(ATS4-PLAT05) Accelrys Catalog: A Search Index for AEP(ATS4-PLAT05) Accelrys Catalog: A Search Index for AEP
(ATS4-PLAT05) Accelrys Catalog: A Search Index for AEPBIOVIA
 
6.Live Framework 和Mesh Services
6.Live Framework 和Mesh Services6.Live Framework 和Mesh Services
6.Live Framework 和Mesh ServicesGaryYoung
 
Monitoring Akka with Kamon 1.0
Monitoring Akka with Kamon 1.0Monitoring Akka with Kamon 1.0
Monitoring Akka with Kamon 1.0Steffen Gebert
 
Hadoop Summit San Diego Feb2013
Hadoop Summit San Diego Feb2013Hadoop Summit San Diego Feb2013
Hadoop Summit San Diego Feb2013Narayan Bharadwaj
 
21st Century Service Oriented Architecture
21st Century Service Oriented Architecture21st Century Service Oriented Architecture
21st Century Service Oriented ArchitectureBob Rhubart
 

Semelhante a Practical functional java script (20)

(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
 
Expendables E-AppStore
Expendables E-AppStoreExpendables E-AppStore
Expendables E-AppStore
 
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
 
(ATS4-APP09)Tips and tricks for Managing Symyx Notebook Server Performance
(ATS4-APP09)Tips and tricks for Managing Symyx Notebook Server Performance(ATS4-APP09)Tips and tricks for Managing Symyx Notebook Server Performance
(ATS4-APP09)Tips and tricks for Managing Symyx Notebook Server Performance
 
Operating the Hyperscale Cloud
Operating the Hyperscale CloudOperating the Hyperscale Cloud
Operating the Hyperscale Cloud
 
SPEC INDIA Java Case Study
SPEC INDIA Java Case StudySPEC INDIA Java Case Study
SPEC INDIA Java Case Study
 
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
 
Build Java Web Application Using Apache Struts
Build Java Web Application Using Apache Struts Build Java Web Application Using Apache Struts
Build Java Web Application Using Apache Struts
 
Sakai Technical Chinese
Sakai Technical ChineseSakai Technical Chinese
Sakai Technical Chinese
 
Sakai Technical
Sakai TechnicalSakai Technical
Sakai Technical
 
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
 
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...
 
Summer training oracle
Summer training   oracle Summer training   oracle
Summer training oracle
 
Backbonification for dummies - Arrrrug 10/1/2012
Backbonification for dummies - Arrrrug 10/1/2012Backbonification for dummies - Arrrrug 10/1/2012
Backbonification for dummies - Arrrrug 10/1/2012
 
(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
 
(ATS4-PLAT05) Accelrys Catalog: A Search Index for AEP
(ATS4-PLAT05) Accelrys Catalog: A Search Index for AEP(ATS4-PLAT05) Accelrys Catalog: A Search Index for AEP
(ATS4-PLAT05) Accelrys Catalog: A Search Index for AEP
 
6.Live Framework 和Mesh Services
6.Live Framework 和Mesh Services6.Live Framework 和Mesh Services
6.Live Framework 和Mesh Services
 
Monitoring Akka with Kamon 1.0
Monitoring Akka with Kamon 1.0Monitoring Akka with Kamon 1.0
Monitoring Akka with Kamon 1.0
 
Hadoop Summit San Diego Feb2013
Hadoop Summit San Diego Feb2013Hadoop Summit San Diego Feb2013
Hadoop Summit San Diego Feb2013
 
21st Century Service Oriented Architecture
21st Century Service Oriented Architecture21st Century Service Oriented Architecture
21st Century Service Oriented Architecture
 

Mais de thinkphp

Knut Morris Pratt Algorithm
Knut Morris Pratt AlgorithmKnut Morris Pratt Algorithm
Knut Morris Pratt Algorithmthinkphp
 
String kmp
String kmpString kmp
String kmpthinkphp
 
String searching
String searching String searching
String searching thinkphp
 
Functional programming in java script
Functional programming in java scriptFunctional programming in java script
Functional programming in java scriptthinkphp
 
Javascript patterns
Javascript patternsJavascript patterns
Javascript patternsthinkphp
 
Placemaker
PlacemakerPlacemaker
Placemakerthinkphp
 
PHP 5.3 And PHP 6 A Look Ahead
PHP 5.3 And PHP 6 A Look AheadPHP 5.3 And PHP 6 A Look Ahead
PHP 5.3 And PHP 6 A Look Aheadthinkphp
 
Atom Web Services
Atom Web ServicesAtom Web Services
Atom Web Servicesthinkphp
 
Json Rpc Proxy Generation With Php
Json Rpc Proxy Generation With PhpJson Rpc Proxy Generation With Php
Json Rpc Proxy Generation With Phpthinkphp
 
Php And Web Services
Php And Web ServicesPhp And Web Services
Php And Web Servicesthinkphp
 
Object Oriented Programming Concepts
Object Oriented Programming ConceptsObject Oriented Programming Concepts
Object Oriented Programming Conceptsthinkphp
 
Ajax Introduction Presentation
Ajax   Introduction   PresentationAjax   Introduction   Presentation
Ajax Introduction Presentationthinkphp
 
Principii Poo
Principii PooPrincipii Poo
Principii Poothinkphp
 

Mais de thinkphp (14)

Knut Morris Pratt Algorithm
Knut Morris Pratt AlgorithmKnut Morris Pratt Algorithm
Knut Morris Pratt Algorithm
 
String kmp
String kmpString kmp
String kmp
 
String searching
String searching String searching
String searching
 
Functional programming in java script
Functional programming in java scriptFunctional programming in java script
Functional programming in java script
 
Javascript patterns
Javascript patternsJavascript patterns
Javascript patterns
 
Placemaker
PlacemakerPlacemaker
Placemaker
 
PHP 5.3 And PHP 6 A Look Ahead
PHP 5.3 And PHP 6 A Look AheadPHP 5.3 And PHP 6 A Look Ahead
PHP 5.3 And PHP 6 A Look Ahead
 
Atom Web Services
Atom Web ServicesAtom Web Services
Atom Web Services
 
Json Rpc Proxy Generation With Php
Json Rpc Proxy Generation With PhpJson Rpc Proxy Generation With Php
Json Rpc Proxy Generation With Php
 
Php And Web Services
Php And Web ServicesPhp And Web Services
Php And Web Services
 
Object Oriented Programming Concepts
Object Oriented Programming ConceptsObject Oriented Programming Concepts
Object Oriented Programming Concepts
 
Ajax Introduction Presentation
Ajax   Introduction   PresentationAjax   Introduction   Presentation
Ajax Introduction Presentation
 
OOP
OOPOOP
OOP
 
Principii Poo
Principii PooPrincipii Poo
Principii Poo
 

Último

4.11.24 Mass Incarceration and the New Jim Crow.pptx
4.11.24 Mass Incarceration and the New Jim Crow.pptx4.11.24 Mass Incarceration and the New Jim Crow.pptx
4.11.24 Mass Incarceration and the New Jim Crow.pptxmary850239
 
Congestive Cardiac Failure..presentation
Congestive Cardiac Failure..presentationCongestive Cardiac Failure..presentation
Congestive Cardiac Failure..presentationdeepaannamalai16
 
Textual Evidence in Reading and Writing of SHS
Textual Evidence in Reading and Writing of SHSTextual Evidence in Reading and Writing of SHS
Textual Evidence in Reading and Writing of SHSMae Pangan
 
ARTERIAL BLOOD GAS ANALYSIS........pptx
ARTERIAL BLOOD  GAS ANALYSIS........pptxARTERIAL BLOOD  GAS ANALYSIS........pptx
ARTERIAL BLOOD GAS ANALYSIS........pptxAneriPatwari
 
ESP 4-EDITED.pdfmmcncncncmcmmnmnmncnmncmnnjvnnv
ESP 4-EDITED.pdfmmcncncncmcmmnmnmncnmncmnnjvnnvESP 4-EDITED.pdfmmcncncncmcmmnmnmncnmncmnnjvnnv
ESP 4-EDITED.pdfmmcncncncmcmmnmnmncnmncmnnjvnnvRicaMaeCastro1
 
Concurrency Control in Database Management system
Concurrency Control in Database Management systemConcurrency Control in Database Management system
Concurrency Control in Database Management systemChristalin Nelson
 
MS4 level being good citizen -imperative- (1) (1).pdf
MS4 level   being good citizen -imperative- (1) (1).pdfMS4 level   being good citizen -imperative- (1) (1).pdf
MS4 level being good citizen -imperative- (1) (1).pdfMr Bounab Samir
 
ClimART Action | eTwinning Project
ClimART Action    |    eTwinning ProjectClimART Action    |    eTwinning Project
ClimART Action | eTwinning Projectjordimapav
 
Unraveling Hypertext_ Analyzing Postmodern Elements in Literature.pptx
Unraveling Hypertext_ Analyzing  Postmodern Elements in  Literature.pptxUnraveling Hypertext_ Analyzing  Postmodern Elements in  Literature.pptx
Unraveling Hypertext_ Analyzing Postmodern Elements in Literature.pptxDhatriParmar
 
4.9.24 School Desegregation in Boston.pptx
4.9.24 School Desegregation in Boston.pptx4.9.24 School Desegregation in Boston.pptx
4.9.24 School Desegregation in Boston.pptxmary850239
 
How to Make a Duplicate of Your Odoo 17 Database
How to Make a Duplicate of Your Odoo 17 DatabaseHow to Make a Duplicate of Your Odoo 17 Database
How to Make a Duplicate of Your Odoo 17 DatabaseCeline George
 
BIOCHEMISTRY-CARBOHYDRATE METABOLISM CHAPTER 2.pptx
BIOCHEMISTRY-CARBOHYDRATE METABOLISM CHAPTER 2.pptxBIOCHEMISTRY-CARBOHYDRATE METABOLISM CHAPTER 2.pptx
BIOCHEMISTRY-CARBOHYDRATE METABOLISM CHAPTER 2.pptxSayali Powar
 
DIFFERENT BASKETRY IN THE PHILIPPINES PPT.pptx
DIFFERENT BASKETRY IN THE PHILIPPINES PPT.pptxDIFFERENT BASKETRY IN THE PHILIPPINES PPT.pptx
DIFFERENT BASKETRY IN THE PHILIPPINES PPT.pptxMichelleTuguinay1
 
31 ĐỀ THI THỬ VÀO LỚP 10 - TIẾNG ANH - FORM MỚI 2025 - 40 CÂU HỎI - BÙI VĂN V...
31 ĐỀ THI THỬ VÀO LỚP 10 - TIẾNG ANH - FORM MỚI 2025 - 40 CÂU HỎI - BÙI VĂN V...31 ĐỀ THI THỬ VÀO LỚP 10 - TIẾNG ANH - FORM MỚI 2025 - 40 CÂU HỎI - BÙI VĂN V...
31 ĐỀ THI THỬ VÀO LỚP 10 - TIẾNG ANH - FORM MỚI 2025 - 40 CÂU HỎI - BÙI VĂN V...Nguyen Thanh Tu Collection
 
Q-Factor General Quiz-7th April 2024, Quiz Club NITW
Q-Factor General Quiz-7th April 2024, Quiz Club NITWQ-Factor General Quiz-7th April 2024, Quiz Club NITW
Q-Factor General Quiz-7th April 2024, Quiz Club NITWQuiz Club NITW
 
Using Grammatical Signals Suitable to Patterns of Idea Development
Using Grammatical Signals Suitable to Patterns of Idea DevelopmentUsing Grammatical Signals Suitable to Patterns of Idea Development
Using Grammatical Signals Suitable to Patterns of Idea Developmentchesterberbo7
 
Beauty Amidst the Bytes_ Unearthing Unexpected Advantages of the Digital Wast...
Beauty Amidst the Bytes_ Unearthing Unexpected Advantages of the Digital Wast...Beauty Amidst the Bytes_ Unearthing Unexpected Advantages of the Digital Wast...
Beauty Amidst the Bytes_ Unearthing Unexpected Advantages of the Digital Wast...DhatriParmar
 
Mythology Quiz-4th April 2024, Quiz Club NITW
Mythology Quiz-4th April 2024, Quiz Club NITWMythology Quiz-4th April 2024, Quiz Club NITW
Mythology Quiz-4th April 2024, Quiz Club NITWQuiz Club NITW
 
Reading and Writing Skills 11 quarter 4 melc 1
Reading and Writing Skills 11 quarter 4 melc 1Reading and Writing Skills 11 quarter 4 melc 1
Reading and Writing Skills 11 quarter 4 melc 1GloryAnnCastre1
 

Último (20)

4.11.24 Mass Incarceration and the New Jim Crow.pptx
4.11.24 Mass Incarceration and the New Jim Crow.pptx4.11.24 Mass Incarceration and the New Jim Crow.pptx
4.11.24 Mass Incarceration and the New Jim Crow.pptx
 
Congestive Cardiac Failure..presentation
Congestive Cardiac Failure..presentationCongestive Cardiac Failure..presentation
Congestive Cardiac Failure..presentation
 
Textual Evidence in Reading and Writing of SHS
Textual Evidence in Reading and Writing of SHSTextual Evidence in Reading and Writing of SHS
Textual Evidence in Reading and Writing of SHS
 
ARTERIAL BLOOD GAS ANALYSIS........pptx
ARTERIAL BLOOD  GAS ANALYSIS........pptxARTERIAL BLOOD  GAS ANALYSIS........pptx
ARTERIAL BLOOD GAS ANALYSIS........pptx
 
ESP 4-EDITED.pdfmmcncncncmcmmnmnmncnmncmnnjvnnv
ESP 4-EDITED.pdfmmcncncncmcmmnmnmncnmncmnnjvnnvESP 4-EDITED.pdfmmcncncncmcmmnmnmncnmncmnnjvnnv
ESP 4-EDITED.pdfmmcncncncmcmmnmnmncnmncmnnjvnnv
 
Concurrency Control in Database Management system
Concurrency Control in Database Management systemConcurrency Control in Database Management system
Concurrency Control in Database Management system
 
MS4 level being good citizen -imperative- (1) (1).pdf
MS4 level   being good citizen -imperative- (1) (1).pdfMS4 level   being good citizen -imperative- (1) (1).pdf
MS4 level being good citizen -imperative- (1) (1).pdf
 
ClimART Action | eTwinning Project
ClimART Action    |    eTwinning ProjectClimART Action    |    eTwinning Project
ClimART Action | eTwinning Project
 
INCLUSIVE EDUCATION PRACTICES FOR TEACHERS AND TRAINERS.pptx
INCLUSIVE EDUCATION PRACTICES FOR TEACHERS AND TRAINERS.pptxINCLUSIVE EDUCATION PRACTICES FOR TEACHERS AND TRAINERS.pptx
INCLUSIVE EDUCATION PRACTICES FOR TEACHERS AND TRAINERS.pptx
 
Unraveling Hypertext_ Analyzing Postmodern Elements in Literature.pptx
Unraveling Hypertext_ Analyzing  Postmodern Elements in  Literature.pptxUnraveling Hypertext_ Analyzing  Postmodern Elements in  Literature.pptx
Unraveling Hypertext_ Analyzing Postmodern Elements in Literature.pptx
 
4.9.24 School Desegregation in Boston.pptx
4.9.24 School Desegregation in Boston.pptx4.9.24 School Desegregation in Boston.pptx
4.9.24 School Desegregation in Boston.pptx
 
How to Make a Duplicate of Your Odoo 17 Database
How to Make a Duplicate of Your Odoo 17 DatabaseHow to Make a Duplicate of Your Odoo 17 Database
How to Make a Duplicate of Your Odoo 17 Database
 
BIOCHEMISTRY-CARBOHYDRATE METABOLISM CHAPTER 2.pptx
BIOCHEMISTRY-CARBOHYDRATE METABOLISM CHAPTER 2.pptxBIOCHEMISTRY-CARBOHYDRATE METABOLISM CHAPTER 2.pptx
BIOCHEMISTRY-CARBOHYDRATE METABOLISM CHAPTER 2.pptx
 
DIFFERENT BASKETRY IN THE PHILIPPINES PPT.pptx
DIFFERENT BASKETRY IN THE PHILIPPINES PPT.pptxDIFFERENT BASKETRY IN THE PHILIPPINES PPT.pptx
DIFFERENT BASKETRY IN THE PHILIPPINES PPT.pptx
 
31 ĐỀ THI THỬ VÀO LỚP 10 - TIẾNG ANH - FORM MỚI 2025 - 40 CÂU HỎI - BÙI VĂN V...
31 ĐỀ THI THỬ VÀO LỚP 10 - TIẾNG ANH - FORM MỚI 2025 - 40 CÂU HỎI - BÙI VĂN V...31 ĐỀ THI THỬ VÀO LỚP 10 - TIẾNG ANH - FORM MỚI 2025 - 40 CÂU HỎI - BÙI VĂN V...
31 ĐỀ THI THỬ VÀO LỚP 10 - TIẾNG ANH - FORM MỚI 2025 - 40 CÂU HỎI - BÙI VĂN V...
 
Q-Factor General Quiz-7th April 2024, Quiz Club NITW
Q-Factor General Quiz-7th April 2024, Quiz Club NITWQ-Factor General Quiz-7th April 2024, Quiz Club NITW
Q-Factor General Quiz-7th April 2024, Quiz Club NITW
 
Using Grammatical Signals Suitable to Patterns of Idea Development
Using Grammatical Signals Suitable to Patterns of Idea DevelopmentUsing Grammatical Signals Suitable to Patterns of Idea Development
Using Grammatical Signals Suitable to Patterns of Idea Development
 
Beauty Amidst the Bytes_ Unearthing Unexpected Advantages of the Digital Wast...
Beauty Amidst the Bytes_ Unearthing Unexpected Advantages of the Digital Wast...Beauty Amidst the Bytes_ Unearthing Unexpected Advantages of the Digital Wast...
Beauty Amidst the Bytes_ Unearthing Unexpected Advantages of the Digital Wast...
 
Mythology Quiz-4th April 2024, Quiz Club NITW
Mythology Quiz-4th April 2024, Quiz Club NITWMythology Quiz-4th April 2024, Quiz Club NITW
Mythology Quiz-4th April 2024, Quiz Club NITW
 
Reading and Writing Skills 11 quarter 4 melc 1
Reading and Writing Skills 11 quarter 4 melc 1Reading and Writing Skills 11 quarter 4 melc 1
Reading and Writing Skills 11 quarter 4 melc 1
 

Practical functional java script

  • 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 "' + x + '"'); }   function request() { $.get('/request', callback); }   request();    
  • 29. Nested Functions: Variables var callback = function(x) { log('received "' + x + '"'); }   var request = function() { $.get('/request', callback); }   request();    
  • 30. Nested Functions: Function-First Style function request() { function callback(x) { log('received "' + x + '"'); } $.get('/request', callback); }   request();    
  • 31. Nested Functions: Pyramid Order function request() { $.get('/request', callback); function callback(x) { log('received "' + x + '"'); } }   request();    
  • 32. Nested Functions: Inlining the Function function request() { $.get('/request', function callback(x) { log('received "' + x + '"'); }); }   request();    
  • 33. Nested Functions: Anonymous function request() { $.get('/request', function (x) { log('received "' + x + '"'); }); }   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