ServersidenessDouglas Crockford   Yahoo! Inc.
Server Side JavaScript•    1996 Netscape LiveWire    PHP-like.    Fail.•    Now Node.js on V8.    Event driven, turn based...
node.js•  node.js implements a web server in a  JavaScript event loop.•  It is a high-performance event pump.fs.readFile(f...
Your stuff runs on both sides  Your stuff        Your stuff    YUI3              YUI3 DOM   node.js    DOM                ...
Turn•    A turn is started by an external    event, such as the completion of an    asynchronous request, a user action,  ...
The Law of Turns Never wait. Never block.  Finish fast.
Turns•    Nothing can ever block, not even I/O.•    Do not poll. Instead, register a    callback.•    This is how browsers...
Long running tasks•    Two solutions for long running    programs:•    Eteration: Break the task into    multiple turns.• ...
Threads are evil•    In systems programming, threads are    a necessary evil.•    In application programming, threads    a...
Two threads•     my_array = [];1.   my_array[my_array.length] = a;2.   my_array[my_array.length] = b;•.     [a, b]•.     [...
Two threads•     my_array = [];1.   my_array[my_array.length] = a;2.   my_array[my_array.length] = b;•.     [a, b]•.     [...
my_array[my_array.length] = a;length_a = my_array.length;my_array[length_a] = a;if (length_a >= my_array.length) {    my_a...
my_array[my_array.length] = a;my_array[my_array.length] = b;length_a = my_array.length;length_b = my_array.length;my_array...
It is impossible to haveapplication integrity whensubject to race conditions.  Read - Modify - Write
Mutual Exclusion•    semaphore•    monitor•    rendezvous•    synchronization•    This used to be operating system    stuf...
Deadlock
Deadlock
Remote Procedure Call•    Combines two great ideas, functions    and networking, producing a really    bad idea.•    Attem...
Turn-based programavoids the problemsbut is unfamiliar to  non-JavaScript  programmers.
Quiz 1function funky(o) {    o = null;}var x = [];funky(x);              A.   null                       B.   []          ...
Quiz 2function swap(a, b) {    var temp = a;    a = b;    b = temp}var x = 1, y = 2;       A.   1swap(x, y);             B...
Quiz 3Make a function that puts a value in a    variable when it is finished.
Pass the name of the             variable.function do_it(inputs, name) {    ...    eval(name +  =  + result);    window[na...
function do_it(inputs, obj, name) {    ...    obj[name] = result;}•    Gives do-it too much authority.
function do_it(inputs, func) {    ...    func(result);}•    We pass a function to do_it.•    do_it cannot abuse the functi...
Callbacks•    Temporal isolation.•    Event handlers.•    Timers.•    Lightweight, powerful, expressive.•    Continuation.
function do_it(inputs, callback) {    ...    callback(result);}do_it(my_inputs, function (result) {    my_object.blah = re...
Generalize.function storer(obj, name) {    return function (result) {        obj[name] = result;    };}do_it(inputs,    st...
function storer_maker(obj) {   return function(name) {       return function (result) {            obj[name] = result;    ...
function once(func) {    return function () {        var f = func;        func = null;        return f.apply(this,argument...
function sequence() {    var slice = Array.prototype.slice,         functions =             slice.call(arguments, 0);    r...
function revokerness(func) {    return {        revocable: function () {            return func.apply(this,               ...
do_it(my_inputs, once(sequence(     storer(my_object, blah),     storer(other_object, wow),     alert)));
Server programming can be        more complicated.•    Call 20 services, each contributing    material for the page, wait ...
Requestorfunction requestor(sync) {    service_request(param,        function (error, result) {            sync(error, res...
Requestor makerfunction request_maker(param) {   return function (sync) {       service_request(param,           function ...
Requestor maker makerfunction request_maker_maker(service) {    return function (param) {        return function (sync) { ...
Requestor maker makerrequest_maker_maker    (service)    (param)    (sync);
Compositionpar([requestor…], sync, timeout);seq([requestor…], sync, timeout);map([requestor…], sync, timeout);
Composition function         makersparor([requestor…], timeout)seqor([requestor…], timeout)mapor([requestor…], timeout)
Also see• Directing JavaScript with Arrowswww.cs.umd.edu/~mwh/papers/jsarrows.pdf•  Reactive Extensions for JavaScripthttp...
Thank you and good night.
Upcoming SlideShare
Loading in …5
×

Douglas Crockford: Serversideness

2,617 views

Published on

Douglas Crockford's presentation at WebExpo Prague 2011. See video http://webexpo.net/prague2011/talk/serversideness/

Published in: Technology, Business

Douglas Crockford: Serversideness

  1. 1. ServersidenessDouglas Crockford Yahoo! Inc.
  2. 2. Server Side JavaScript• 1996 Netscape LiveWire PHP-like. Fail.• Now Node.js on V8. Event driven, turn based execution. Win.
  3. 3. node.js• node.js implements a web server in a JavaScript event loop.• It is a high-performance event pump.fs.readFile(filename, encoding, function (err, data) {...})• Everything is (or can be) non- blocking.• Except: – some synchronous functions – require
  4. 4. Your stuff runs on both sides Your stuff Your stuff YUI3 YUI3 DOM node.js DOM JS JS/V8 Browser
  5. 5. Turn• A turn is started by an external event, such as the completion of an asynchronous request, a user action, or the ticking of the clock.• A callback function associated with the event is called. It runs to completion. When it returns, the turn ends.• No need for threads. No races. No deadlocks.
  6. 6. The Law of Turns Never wait. Never block. Finish fast.
  7. 7. Turns• Nothing can ever block, not even I/O.• Do not poll. Instead, register a callback.• This is how browsers work.• This is how servers should also work.
  8. 8. Long running tasks• Two solutions for long running programs:• Eteration: Break the task into multiple turns.• Move the task into a separate process (workers).
  9. 9. Threads are evil• In systems programming, threads are a necessary evil.• In application programming, threads are just evil.• Threads provide a deceptively simple model of concurrency.• Threads are subject to races and deadlocks.
  10. 10. Two threads• my_array = [];1. my_array[my_array.length] = a;2. my_array[my_array.length] = b;•. [a, b]•. [b, a]
  11. 11. Two threads• my_array = [];1. my_array[my_array.length] = a;2. my_array[my_array.length] = b;•. [a, b]•. [b, a]•. [a]•. [b]
  12. 12. my_array[my_array.length] = a;length_a = my_array.length;my_array[length_a] = a;if (length_a >= my_array.length) { my_array.length = length_a + 1;}
  13. 13. my_array[my_array.length] = a;my_array[my_array.length] = b;length_a = my_array.length;length_b = my_array.length;my_array[length_a] = a;if (length_a >= my_array.length){my_array[length_b] = b; my_array.length = length_a +1;}
  14. 14. It is impossible to haveapplication integrity whensubject to race conditions. Read - Modify - Write
  15. 15. Mutual Exclusion• semaphore• monitor• rendezvous• synchronization• This used to be operating system stuff.• It has leaked into applications because of networking and the multi-
  16. 16. Deadlock
  17. 17. Deadlock
  18. 18. Remote Procedure Call• Combines two great ideas, functions and networking, producing a really bad idea.• Attempts to isolate programs from time. The program blacks out.• In reading the program, it is by design difficult to see where time is lost.• This can result in a terrible experience for the user. Lost time
  19. 19. Turn-based programavoids the problemsbut is unfamiliar to non-JavaScript programmers.
  20. 20. Quiz 1function funky(o) { o = null;}var x = [];funky(x); A. null B. [] C. undefinedalert(x); D. throw
  21. 21. Quiz 2function swap(a, b) { var temp = a; a = b; b = temp}var x = 1, y = 2; A. 1swap(x, y); B. 2 C. undefined D. throwalert(x);
  22. 22. Quiz 3Make a function that puts a value in a variable when it is finished.
  23. 23. Pass the name of the variable.function do_it(inputs, name) { ... eval(name + = + result); window[name] = result;}• Not only bad practice, but illegal in ES5/strict.
  24. 24. function do_it(inputs, obj, name) { ... obj[name] = result;}• Gives do-it too much authority.
  25. 25. function do_it(inputs, func) { ... func(result);}• We pass a function to do_it.• do_it cannot abuse the function.• The function cannot abuse do_it.• func is a callback.
  26. 26. Callbacks• Temporal isolation.• Event handlers.• Timers.• Lightweight, powerful, expressive.• Continuation.
  27. 27. function do_it(inputs, callback) { ... callback(result);}do_it(my_inputs, function (result) { my_object.blah = result;});
  28. 28. Generalize.function storer(obj, name) { return function (result) { obj[name] = result; };}do_it(inputs, storer(my_object, blah));
  29. 29. function storer_maker(obj) { return function(name) { return function (result) { obj[name] = result; }; };}my_storer = storer_maker(my_object);do_it(my_inputs, my_storer(blah));
  30. 30. function once(func) { return function () { var f = func; func = null; return f.apply(this,arguments); };}do_it(my_inputs,
  31. 31. function sequence() { var slice = Array.prototype.slice, functions = slice.call(arguments, 0); return function () { var args = slice.call(arguments,0); functions.forEach(function(func) { func.apply(null, args);
  32. 32. function revokerness(func) { return { revocable: function () { return func.apply(this, arguments); }, revoker: function () { func = null; } };
  33. 33. do_it(my_inputs, once(sequence( storer(my_object, blah), storer(other_object, wow), alert)));
  34. 34. Server programming can be more complicated.• Call 20 services, each contributing material for the page, wait until all respond, then assemble the result.• Call a service, use its result to call another service, avoiding deeply nested event handlers.
  35. 35. Requestorfunction requestor(sync) { service_request(param, function (error, result) { sync(error, result); });}
  36. 36. Requestor makerfunction request_maker(param) { return function (sync) { service_request(param, function (error, result) { sync(error, result); }); };}
  37. 37. Requestor maker makerfunction request_maker_maker(service) { return function (param) { return function (sync) { service(param, function (error, result) { sync(error, result); }); }; };}
  38. 38. Requestor maker makerrequest_maker_maker (service) (param) (sync);
  39. 39. Compositionpar([requestor…], sync, timeout);seq([requestor…], sync, timeout);map([requestor…], sync, timeout);
  40. 40. Composition function makersparor([requestor…], timeout)seqor([requestor…], timeout)mapor([requestor…], timeout)
  41. 41. Also see• Directing JavaScript with Arrowswww.cs.umd.edu/~mwh/papers/jsarrows.pdf• Reactive Extensions for JavaScripthttp://blogs.msdn.com/b/rxteam/archive/2010/03/17/reactive-extensions-for-javascript.aspx
  42. 42. Thank you and good night.

×