SlideShare a Scribd company logo
1 of 85
@crichardson
NodeJS: the good parts?
A skeptic’s view
Chris Richardson
Author of POJOs in Action
Founder of the original CloudFoundry.com
@crichardson
chris.richardson@springsource.com
http://plainoldobjects.com
@crichardson
Presentation goal
How a curmudgeonly
server-side Java developer
discovered an appreciation
for NodeJS and JavaScript
@crichardson
About Chris
@crichardson
(About Chris)
@crichardson
About Chris()
@crichardson
About Chris
@crichardson
About Chris
http://www.theregister.co.uk/2009/08/19/springsource_cloud_foundry/
@crichardson
vmc push About-Chris
Developer Advocate
Signup at http://cloudfoundry.com
@crichardson
Agenda
Overview of NodeJS
Building a front-end server with NodeJS
Taming tangled asynchronous code with promises
@crichardson
What’s NodeJS?
Designed for DIRTy apps
@crichardson
Small but growing rapidly
Busy!
@crichardson
NodeJS Hello World
app.js
$ node app.js
$ curl http://localhost:1337
http://nodejs.org/
Load a module
request handler
@crichardson
NodeJS
JavaScript
Reactor
pattern
Modules
@crichardson
NodeJS
JavaScript
Reactor
pattern
Modules
@crichardson
Dynamic, weakly-typed
Dynamic:
Types are associated with values - not variables
Define new program elements at runtime
Weakly typed:
Leave out arguments to methods
Access non-existent object properties
Weird implicit conversions: 99 == “99”!
truthy and falsy values
Comprehensive tests are essential
@crichardson
JavaScript is object-oriented
> var fred = {name: “Fred”, gender: “Male”};
undefined
> fred.name
“Fred”
> console.log("reading age=" + fred.age);
reading age=undefined
undefined
> fred.age = 99;
99
> fred
{ name: 'Fred',
gender: 'Male',
age: 99 }
> delete fred.age
true
> fred
{ name: 'Fred', gender: 'Male' }
Unordered key-value pairs
Keys = properties
Add property
Delete property
@crichardson
JavaScript “classes”
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function () { console.log("Hello " + this.name); };
var chris = new Person("Chris");
chris.sayHello();
Looks like a
constructor?!?
What’s that?!?!
This Java-like syntax is a mess
because JavaScript isn’t class
based
Looks familiar
@crichardson
overrides
JavaScript is a prototypal
language
__proto__
a 99
__proto__
a 100
b 200
inherited
Prototype
X
Y
@crichardson
Prototypal code
$ node
> var person = {};
undefined
> person.sayHello = function () { console.log("Hello " + this.name); };
[Function]
> var chris = Object.create(person, {name: {value: "Chris"}});
undefined
> var sarah = Object.create(person, {name: {value: "Sarah"}});
undefined
> chris.sayHello();
Hello Chris
undefined
> sarah.sayHello();
Hello Sarah
undefined
> chris.sayHello = function () { console.log("Hello mate: " + this.name); };
[Function]
> chris.sayHello();
Hello mate: Chris
undefined
Not defined
here
prototype properties
@crichardson
JavaScript is Functional
function makeGenerator(nextFunction) {
var value = 0;
return function() {
var current = value;
value = nextFunction(value);
return current;
};
}
var inc = makeGenerator(function (x) {return x + 1; });
> inc()
0
> inc()
1
Pass function as an
argument
Return a function
closure
@crichardson
Partial function application
> var join = require("path").join;
undefined
> join("/x", "y")
'/x/y'
> var withinx = join.bind(undefined, "/x");
undefined
> withinx("y");
'/x/y'
>
partially apply join
@crichardson
Created in a hurry with the
goal of looking like Java
The ‘Java...’ name creates expectations that it can’t satisfy
Fake classes: Hides prototypes BUT still seems weird
global namespace
scope of vars is confusing
Missing return statement = confusion
‘function’ is really verbose
‘this’ is dynamically scoped
@crichardson
JavaScript is the only way to
get things done in the
browser
@crichardson
Stockholm syndrome
“Stockholm syndrome ... is a psychological
phenomenon in which hostages ... have
positive feelings toward their captors,
sometimes to the point of defending them...”
http://en.wikipedia.org/wiki/Stockholm_syndrome
@crichardson
Martin Fowler once said:
"...I'm one of those who despairs that a
language with such deep flaws plays such an
important role in computation. Still the
consequence of this is that we must take
javascript seriously as a first-class language
and concentrate on how to limit the damage
its flaws cause. ...."
http://martinfowler.com/bliki/gotoAarhus2012.html
@crichardson
Use just the good parts
@crichardson
Use a better language that
compiles to JavaScript
TypeScript
Typed parameters and fields
Classes and interfaces (dynamic structural typing)
Dart
Class-based OO
Optional static typing
Bidirectional binding with DOM elements
@crichardson
CoffeeScript Hello World
http = require('http')
class HttpRequestHandler
constructor: (@message) ->
handle: (req, res) =>
res.writeHead(200, {'Content-Type': 'text/plain'})
res.end(@message + 'n')
handler = new HttpRequestHandler "Hi There from CoffeeScript"
server = http.createServer(handler.handle)
server.listen(1338, '127.0.0.1')
console.log('Server running at http://127.0.0.1:1338/')
Classes :-)
Bound method
@crichardson
NodeJS
JavaScript
Reactor
pattern
Modules
@crichardson
About the Reactor pattern
Defined by Doug Schmidt in 1995
Pattern for writing scalable servers
Alternative to thread-per-connection model
Single threaded event loop dispatches events on
handles (e.g. sockets, file descriptors) to event handlers
@crichardson
Reactor pattern structure
Event Handler
handle_event(type)
get_handle()
Initiation Dispatcher
handle_events()
register_handler(h)
select(handlers)
for each h in handlers
h.handle_event(type)
end loop
handle
Synchronous Event
Demultiplexer
select()
owns
notifies
uses
handlers
@crichardson
Benefits:
Separation of concerns - event handlers separated
from low-level mechanism
More efficient - no thread context switching
Simplified concurrency - single threaded
@crichardson
Drawbacks:
Non-pre-emptive - handlers can’t block/take a long
time
Difficult to understand and debug - inverted flow of
control
@crichardson
NodeJS event loop implements
the Reactor pattern
@crichardson
Application code
Event-driven architecture
NodeJS event loop
Basic networking/file-system/etc.
HTTP DB driver ...
Event
listener
Callback
function
One
time
events
Recurring
events
@crichardson
Getting notified: Callback
example
var fs = require("fs");
function statFile(path) {
fs.stat(path, function (err, stat) {
if (err) {
console.log("Stat failed: " + path, err);
throw err;
}
console.log("stat result=" + path, stat);
});
};
By convention: first
param is error object
By convention: Last
arg is a callback
Callbacks are
good for one
time
notifications
@crichardson
Getting notified: event
listeners
EventEmitter class - inherit or use
Listener registration methods:
on(eventName, listener)
once(eventName, listener)
Emitting events
emit(eventName, args...)
‘error’ event = special case: no listener print stack trace and
exit!
Good for
recurring
events
@crichardson
Event listener example
var fs = require("fs");
var readStream = fs.createReadStream("events.js", {encoding: "utf-8"});
// ReadStream << ReadableStream << EventEmitter
readStream.on('open', function (fd) {
console.log("opened with fd=", fd);
});
// Node v0.10 has readable instead: this is deprecated
readStream.on('data', function (data) {
console.log("data=", data);
});
Register listener
Register listener
@crichardson
Callback hell
function times2(x, callback) {
setTimeout(function () {
callback(x * 2)}, 500);
}
function plus3(x, callback) {
setTimeout(function (){
callback(x + 3)}, 500);
}
function displayResult(z) {
console.log("The result is=", z);
}
function plus3AndThenTimes2(x, callback)
{
plus3(x, function (y) {
times2(y, callback)
})
}
plus3AndThenTimes2(10, displayResults);
function sum(a, b, callback) {
setTimeout(function () {
callback(a + b);
}, 500);
}
function plus3PlusTimes2(x, callback) {
var p3, t2;
function perhapsDone() {
if (p3 & t2)
sum(p3, t2, callback);
};
plus3(x, function (y) {
p3 = y;
perhapsDone();
});
times2(x, function (y) {
t2 = y;
perhapsDone();
});
}
plus3PlusTimes2(10, displayResult);
times2(plus3(x)) times2(x) + plus3(x)
@crichardson
Long running computations
Long running computation blocks event loop for
other requests
Need to run outside of main event loop
Options:
Community: web workers threads
Built-in: NodeJS child processes
@crichardson
Using child processes
var child = require('child_process').fork('child.js');
function sayHelloToChild() {
child.send({hello: "child"});
}
setTimeout(sayHelloToChild, 1000);
child.on('message', function(m) {
console.log('parent received:', m);
});
function kill() {
child.kill();
}
setTimeout(kill, 2000);
process.on('message', function (m) {
console.log("child received message=", m);
process.send({ihateyou: "you ruined my life"})
});
parent.js
child.js
Create child process
Send message to child
@crichardson
NodeJS
JavaScript
Reactor
pattern
Modules
Core built-in modules
Basic networking
HTTP(S)
Filesystem
Events
Timers
...
@crichardson
Thousands of community
developed modules
https://npmjs.org/
web frameworks, SQL/NoSQL
database, drivers, messaging, utilities...
@crichardson
What’s a module?
One or more JavaScript files
Optional native code:
Compiled during installation
JavaScript != systems programming language
Package.json - metadata including dependencies
exports.sayHello = function () {
console.log(“Hello”);
}
foo.js
@crichardson
Easy to install
$ npm install package-name
@crichardson
Easy to use
var http = require(“http”)
var server = http.createServer...
Core module OR
Path to file OR
module in node_modules
Module’s exports
@crichardson
Developing with NodeJS
modules
Core modules
Community modules
Your modules
Application code
@crichardson
Lots of modules BUT...
Variable quality
Multiple incomplete MySQL drivers, e.g. without
connection pooling!
Often abandoned
...
@crichardson
To summarize
NodeJS
JavaScript
Reactor patternModules
Flawed and
misunderstood
Scalable yet
costly and
often
unnecessary
Rich but
variable quality
@crichardson
Alternative technologies
Atmosphere - portable event delivery
Netty - asynchronous I/O
Vert.x
SpringSource’s Reactor project
...
@crichardson
So why care about
NodeJS?
Easy to write scalable network services
Easy to push events to the browser
Easy to get (small) stuff done
It has a role to play in modern
application architecture
@crichardson
Evolving from a monolithic
architecture....
WAR
Shipping
Service
Accounting
Service
Inventory
Service
StoreFrontUI
@crichardson
... to a micro-service architecture
Store front web application
shipping web application
inventory web application
Accounting
Service
StoreFrontUI
accounting web application
Shipping
Service
Inventory
Service
@crichardson
Browser
WAR
StoreFrontUI
Model
View Controller
Presentation layer evolution....
HTML / HTTP
+
JavaScript
@crichardson
Browser Web application
RESTful
EndpointsModel
View Controller
...Presentation layer evolution
JSON-REST
HTML 5 -
JavaScript
No elaborate, server-side web framework
required
Event
publisher
Events
Static
content
@crichardson
NodeJS as an API gateway
Browser
Service 1
Service 2
Message
Bus
HTML 5/
Java
Script
Socket.io
client
Events
RESTful WS
Server
application
Socket.io
server
Node JS
Service 3
RESTful
WS
@crichardson
Agenda
Overview of NodeJS
Building a front-end server with NodeJS
Taming tangled asynchronous code with promises
@crichardson
Serving static content
@crichardson
Using low-level APIs
var http = require('http'), path = require('path'), mime = require('mime'), fs = require("fs");
var server = http.createServer(function (req, res) {
var filePath;
if (req.url == '/') {
filePath = 'public/index.html';
} else {
filePath = 'public' + req.url;
}
fs.exists(filePath, function (exists) {
if (exists) {
res.writeHead(200, {"content-type": mime.lookup(path.basename(filePath)) });
fs.createReadStream(filePath).pipe(res);
} else {
res.writeHead(404, {'Content-Type': 'text/plain'});
res.write('Error 404: resource not found.');
res.end();
}
});
}
);
server.listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
Uses file
extension
Cool!
@crichardson
Using the express web
framework
var express = require('express')
, http = require('http')
, app = express()
, server = http.createServer(app)
;
app.configure(function(){
app.use(express.static(__dirname + '/public'));
});
server.listen(8081);
@crichardson
RESTful web services
@crichardson
Implementing RESTful WS
with Express
var express = require('express'),
http = require('http'),
path = require('path');
var app = express();
var server = http.createServer(app);
app.get('/portfolio/:userId', function (req, res) {
var portfolio = retrievePortfolio(req.params.userId);
res.json(portfolio);
});
Easy URL
routing and
destructuring
@crichardson
Proxying to backend server
express = require('express')
request = require('request')
app = express.createServer()
proxyToBackend = (baseUrl) ->
(req, res) ->
callback = (error, response, body) -> console.log("error=", error)
originRequest = request(baseUrl + req.url, callback)
req.pipe(originRequest)
originRequest.pipe(res)
app.get('/restaurant/*', proxyToBackend('http://available-restaurant....com'))
app.post('/orders', proxyToBackend('http://restaurant-management...com'))
app.get('/orders', proxyToBackend(''http://restaurant-management...com'))
Returns a request handler
that proxies to baseUrl
@crichardson
Delivering events to the
browser
@crichardson
NodeJS clock example
Increments every
second
@crichardson
Socket.io - Server side
var express = require('express')
, http = require('http')
, app = express()
, server = http.createServer(app)
, io = require('socket.io').listen(server)
;
app.configure(function(){
app.use(express.static(__dirname + '/public'));
});
server.listen(8081);
io.sockets.on('connection', function (socket) {
	 var counter = 0;
	 function tick() {
	 	 counter = counter + 1;
	 	 socket.emit('tick', counter);
	 };
	 setInterval(tick, 1000);
});
handle new
connection
Send tick event to
browser every 1 sec
initializes socket.io
@crichardson
Socket.io - client side using the
knockout.js MVVM framework
var socket = io.connect(location.hostname);
function ClockModel() {
self.ticker = ko.observable(1);
socket.on('tick', function (data) {
self.ticker(data);
});
};
ko.applyBindings(new ClockModel());
<html>
<body>
The event is <span data-bind="text: ticker"></span>
<script src="/socket.io/socket.io.js"></script>
<script src="/knockout-2.0.0.js"></script>
<script src="/clock.js"></script>
</body>
</html>
clock.js
Connect to
socket.io
Subscribe
to tick event
Bind to model
Update
model
@crichardson
Distributed NodeJS clock
example
Browser NodeJS NodeJS
RabbitMQ
ProducerConsumer
socket.iosocket.io
@crichardson
AMQP Publisher
var amqp = require('amqp'),
amqpConnection = amqp.createConnection(...),
tickTockExchange;
function tick() {
var message = { tick: Date.now() };
tickTockExchange.publish("tickTock", message, {
mandatory: true,
contentType: "text/plain"
});
};
amqpConnection.on('ready',
function () {
tickTockExchange =
amqpConnection.exchange("tickTock",
options = {passive: false, type: 'fanout'});
tickTockExchange.on('open', function () { setInterval(tick, 1000) });
});
Connect to
AMQP
Ensure
exchange
exists
Publish
message
Initialize timer
@crichardson
AMQP socket.iovar express = require('express')
, http = require('http')
, amqp = require(‘amqp’)
....;
server.listen(8081);
...
var amqpCon = amqp.createConnection(...);
io.sockets.on('connection', function (socket) {
function amqpMessageHandler(message, headers, deliveryInfo) {
var m = JSON.parse(message.data.toString());
socket.emit(‘tick’, m);
};
amqpCon.queue(“”, {},
function(queue) {
queue.bind(“tickTock”, “”);
queue.subscribe(amqpMessageHandler);
});
});
Connect to
AMQP queue
Subscribe to
AMQP queue
Republish
as socket.io
event
https://github.com/cer/nodejs-clock
@crichardson
Agenda
Overview of NodeJS
Building a front-end server with NodeJS
Taming tangled asynchronous code with promises
@crichardson
Async code = callback hell
Scenarios:
Sequential: A B C
Fork and join: A and B C
Code quickly becomes very messy
@crichardson
Simplifying code with
Promises (a.k.a. Futures)
Functions return a promise - no callback parameter
A promise represents an eventual outcome
Use a library of functions for transforming and
composing promises
Promises/A+ specification - http://promises-aplus.github.io/promises-spec
when.js (part of cujo.js by SpringSource) is a popular
implementation
@crichardson
Taming callback hell 1
function times2(x) {
var deferred = when.defer();
setTimeout(function () {
deferred.resolve(x * 2)}, 500);
return deferred.promise;
}
times2(plus3(x)) Create a deferred
Return a promise
Eventually supply a value
function plus3AndThenTimes2(x) {
return plus3(x).then(times2);
}
plus3AndThenTimes2(10).
then(displayResult);
Transform value in
promise
function plus3(x) {
var deferred = when.defer();
setTimeout(function () {
deferred.resolve(x + 3) }, 500);
return deferred.promise;
}
Simpler, almost
synchronous-style code
@crichardson
Taming callback hell 2
function sum(a, b) {
var deferred = when.defer();
setTimeout(function () {
deferred.resolve(a + b);
}, 500);
return deferred.promise;
}
function plus3PlusTimes2(x) {
var p3 = plus3(x),
t2 = times2(x);
return when.join(p3, t2).spread(sum);
}
plus3PlusTimes2(10).then(displayResult);
times2(x) + plus3(x)
Combine results
of two promises
Call with array
elements as
arguments
@crichardson
Calling non-promise code
var deferred = when.defer();
fs.stat(path, function (err, statInfo) {
if (err)
deferred.reject(err);
else
deferred.resolve(statInfo);
}
var promise = deferred.promise;
var nodefn = require("when/node/function");
var promise = nodefn.call(fs.stat, path)
Hides
boilerplate
code
@crichardson
Filesystem scanner example
Read contents of directory
Use stat to determine if directory or file
Recurse on directories
Merge the results
@crichardson
Read contents of directory
function findFilesInDir(dir) {
var directoryContents =
nodefn.call(self.fs.readdir, dir);
...
}
Returns promise containing
an array of file names
@crichardson
Create absolute paths
function findFilesInDir(dir) {
var directoryContents = ...
var toAbsolute = join.bind(undefined, dir)
var absolutePaths = when.map(directoryContents, toAbsolute);
...
}
Partially apply
join()
@crichardson
Use stat to determine if
directory or file
function findFilesInDir(dir) {
var directoryContents = ...
var absolutePaths = ...
var statTasks = when.map(absolutePaths, makeStatTask);
var statResults = parallel(statTasks);
...
}
function makeStatTask(path) {
return function () {
function makeStatInfo(stats) {
return {path: path, isdir: stats.isDirectory(),
ctime: stats.ctime};
}
return nodefn.call(self.fs.stat, path).then(makeStatInfo);
};
}
Execute stats in
parallel
@crichardson
Recurse on directories
function findFilesInDir(dir) {
...
var statResults = ...;
var listOfListsOfFiles =
when.map(statResults, processStatInfo);
...
}
function processStatInfo(statInfo) {
if (statInfo.isdir) {
return findFilesInDir(statInfo.path);
} else {
return [statInfo.path];
}
}
Map each stat
result to a list of
files
@crichardson
Flatten array of arrays of file
paths
function findFilesInDir(dir) {
...
var listOfListsOfFiles = ...;
return when.reduce(listOfListsOfFiles,
concatenateLists, []);
}
function concatenateLists(currentResult, value, index, total)
{
return currentResult.concat(value);
}
@crichardson
Summary
JavaScript is a very flawed language
The asynchronous model is often unnecessary; very
constraining; and adds complexity
BUT despite those problems
Today, NodeJS is remarkably useful for building network-
focussed components
@crichardson
Questions?
@crichardson chris.richardson@springsource.com
http://plainoldobjects.com - code and slides
www.cloudfoundry.com

More Related Content

What's hot

A Pattern Language for Microservices (@futurestack)
A Pattern Language for Microservices (@futurestack)A Pattern Language for Microservices (@futurestack)
A Pattern Language for Microservices (@futurestack)Chris Richardson
 
#hacksummit 2016 - event-driven microservices – Events on the outside, on the...
#hacksummit 2016 - event-driven microservices – Events on the outside, on the...#hacksummit 2016 - event-driven microservices – Events on the outside, on the...
#hacksummit 2016 - event-driven microservices – Events on the outside, on the...Chris Richardson
 
Building and deploying microservices with event sourcing, CQRS and Docker (Be...
Building and deploying microservices with event sourcing, CQRS and Docker (Be...Building and deploying microservices with event sourcing, CQRS and Docker (Be...
Building and deploying microservices with event sourcing, CQRS and Docker (Be...Chris Richardson
 
Gluecon: Using sagas to maintain data consistency in a microservice architecture
Gluecon: Using sagas to maintain data consistency in a microservice architectureGluecon: Using sagas to maintain data consistency in a microservice architecture
Gluecon: Using sagas to maintain data consistency in a microservice architectureChris Richardson
 
Events on the outside, on the inside and at the core (jfokus jfokus2016)
Events on the outside, on the inside and at the core (jfokus jfokus2016)Events on the outside, on the inside and at the core (jfokus jfokus2016)
Events on the outside, on the inside and at the core (jfokus jfokus2016)Chris Richardson
 
Building and deploying microservices with event sourcing, CQRS and Docker (QC...
Building and deploying microservices with event sourcing, CQRS and Docker (QC...Building and deploying microservices with event sourcing, CQRS and Docker (QC...
Building and deploying microservices with event sourcing, CQRS and Docker (QC...Chris Richardson
 
Developing microservices with aggregates (devnexus2017)
Developing microservices with aggregates (devnexus2017)Developing microservices with aggregates (devnexus2017)
Developing microservices with aggregates (devnexus2017)Chris Richardson
 
#JaxLondon: Building microservices with Scala, functional domain models and S...
#JaxLondon: Building microservices with Scala, functional domain models and S...#JaxLondon: Building microservices with Scala, functional domain models and S...
#JaxLondon: Building microservices with Scala, functional domain models and S...Chris Richardson
 
Developing functional domain models with event sourcing (oakjug, sfscala)
Developing functional domain models with event sourcing (oakjug, sfscala)Developing functional domain models with event sourcing (oakjug, sfscala)
Developing functional domain models with event sourcing (oakjug, sfscala)Chris Richardson
 
Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...Chris Richardson
 
Microservices and Redis #redisconf Keynote
Microservices and Redis #redisconf KeynoteMicroservices and Redis #redisconf Keynote
Microservices and Redis #redisconf KeynoteChris Richardson
 
Building microservices with Scala, functional domain models and Spring Boot
Building microservices with Scala, functional domain models and Spring BootBuilding microservices with Scala, functional domain models and Spring Boot
Building microservices with Scala, functional domain models and Spring BootChris Richardson
 
QCONSF - ACID Is So Yesterday: Maintaining Data Consistency with Sagas
QCONSF - ACID Is So Yesterday: Maintaining Data Consistency with SagasQCONSF - ACID Is So Yesterday: Maintaining Data Consistency with Sagas
QCONSF - ACID Is So Yesterday: Maintaining Data Consistency with SagasChris Richardson
 
Developing event-driven microservices with event sourcing and CQRS (london Ja...
Developing event-driven microservices with event sourcing and CQRS (london Ja...Developing event-driven microservices with event sourcing and CQRS (london Ja...
Developing event-driven microservices with event sourcing and CQRS (london Ja...Chris Richardson
 
There is no such thing as a microservice! (oracle code nyc)
There is no such thing as a microservice! (oracle code nyc)There is no such thing as a microservice! (oracle code nyc)
There is no such thing as a microservice! (oracle code nyc)Chris Richardson
 
OReilly SACON2018 - Events on the outside, on the inside, and at the core
OReilly SACON2018 - Events on the outside, on the inside, and at the coreOReilly SACON2018 - Events on the outside, on the inside, and at the core
OReilly SACON2018 - Events on the outside, on the inside, and at the coreChris Richardson
 
ArchSummit Shenzhen - Using sagas to maintain data consistency in a microserv...
ArchSummit Shenzhen - Using sagas to maintain data consistency in a microserv...ArchSummit Shenzhen - Using sagas to maintain data consistency in a microserv...
ArchSummit Shenzhen - Using sagas to maintain data consistency in a microserv...Chris Richardson
 
Omnikron webbinar - Microservices: enabling the rapid, frequent, and reliable...
Omnikron webbinar - Microservices: enabling the rapid, frequent, and reliable...Omnikron webbinar - Microservices: enabling the rapid, frequent, and reliable...
Omnikron webbinar - Microservices: enabling the rapid, frequent, and reliable...Chris Richardson
 
CQRS and Event Sourcing with Akka, Cassandra and RabbitMQ
CQRS and Event Sourcing with Akka, Cassandra and RabbitMQCQRS and Event Sourcing with Akka, Cassandra and RabbitMQ
CQRS and Event Sourcing with Akka, Cassandra and RabbitMQMiel Donkers
 
A pattern language for microservices (melbourne)
A pattern language for microservices (melbourne)A pattern language for microservices (melbourne)
A pattern language for microservices (melbourne)Chris Richardson
 

What's hot (20)

A Pattern Language for Microservices (@futurestack)
A Pattern Language for Microservices (@futurestack)A Pattern Language for Microservices (@futurestack)
A Pattern Language for Microservices (@futurestack)
 
#hacksummit 2016 - event-driven microservices – Events on the outside, on the...
#hacksummit 2016 - event-driven microservices – Events on the outside, on the...#hacksummit 2016 - event-driven microservices – Events on the outside, on the...
#hacksummit 2016 - event-driven microservices – Events on the outside, on the...
 
Building and deploying microservices with event sourcing, CQRS and Docker (Be...
Building and deploying microservices with event sourcing, CQRS and Docker (Be...Building and deploying microservices with event sourcing, CQRS and Docker (Be...
Building and deploying microservices with event sourcing, CQRS and Docker (Be...
 
Gluecon: Using sagas to maintain data consistency in a microservice architecture
Gluecon: Using sagas to maintain data consistency in a microservice architectureGluecon: Using sagas to maintain data consistency in a microservice architecture
Gluecon: Using sagas to maintain data consistency in a microservice architecture
 
Events on the outside, on the inside and at the core (jfokus jfokus2016)
Events on the outside, on the inside and at the core (jfokus jfokus2016)Events on the outside, on the inside and at the core (jfokus jfokus2016)
Events on the outside, on the inside and at the core (jfokus jfokus2016)
 
Building and deploying microservices with event sourcing, CQRS and Docker (QC...
Building and deploying microservices with event sourcing, CQRS and Docker (QC...Building and deploying microservices with event sourcing, CQRS and Docker (QC...
Building and deploying microservices with event sourcing, CQRS and Docker (QC...
 
Developing microservices with aggregates (devnexus2017)
Developing microservices with aggregates (devnexus2017)Developing microservices with aggregates (devnexus2017)
Developing microservices with aggregates (devnexus2017)
 
#JaxLondon: Building microservices with Scala, functional domain models and S...
#JaxLondon: Building microservices with Scala, functional domain models and S...#JaxLondon: Building microservices with Scala, functional domain models and S...
#JaxLondon: Building microservices with Scala, functional domain models and S...
 
Developing functional domain models with event sourcing (oakjug, sfscala)
Developing functional domain models with event sourcing (oakjug, sfscala)Developing functional domain models with event sourcing (oakjug, sfscala)
Developing functional domain models with event sourcing (oakjug, sfscala)
 
Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...
 
Microservices and Redis #redisconf Keynote
Microservices and Redis #redisconf KeynoteMicroservices and Redis #redisconf Keynote
Microservices and Redis #redisconf Keynote
 
Building microservices with Scala, functional domain models and Spring Boot
Building microservices with Scala, functional domain models and Spring BootBuilding microservices with Scala, functional domain models and Spring Boot
Building microservices with Scala, functional domain models and Spring Boot
 
QCONSF - ACID Is So Yesterday: Maintaining Data Consistency with Sagas
QCONSF - ACID Is So Yesterday: Maintaining Data Consistency with SagasQCONSF - ACID Is So Yesterday: Maintaining Data Consistency with Sagas
QCONSF - ACID Is So Yesterday: Maintaining Data Consistency with Sagas
 
Developing event-driven microservices with event sourcing and CQRS (london Ja...
Developing event-driven microservices with event sourcing and CQRS (london Ja...Developing event-driven microservices with event sourcing and CQRS (london Ja...
Developing event-driven microservices with event sourcing and CQRS (london Ja...
 
There is no such thing as a microservice! (oracle code nyc)
There is no such thing as a microservice! (oracle code nyc)There is no such thing as a microservice! (oracle code nyc)
There is no such thing as a microservice! (oracle code nyc)
 
OReilly SACON2018 - Events on the outside, on the inside, and at the core
OReilly SACON2018 - Events on the outside, on the inside, and at the coreOReilly SACON2018 - Events on the outside, on the inside, and at the core
OReilly SACON2018 - Events on the outside, on the inside, and at the core
 
ArchSummit Shenzhen - Using sagas to maintain data consistency in a microserv...
ArchSummit Shenzhen - Using sagas to maintain data consistency in a microserv...ArchSummit Shenzhen - Using sagas to maintain data consistency in a microserv...
ArchSummit Shenzhen - Using sagas to maintain data consistency in a microserv...
 
Omnikron webbinar - Microservices: enabling the rapid, frequent, and reliable...
Omnikron webbinar - Microservices: enabling the rapid, frequent, and reliable...Omnikron webbinar - Microservices: enabling the rapid, frequent, and reliable...
Omnikron webbinar - Microservices: enabling the rapid, frequent, and reliable...
 
CQRS and Event Sourcing with Akka, Cassandra and RabbitMQ
CQRS and Event Sourcing with Akka, Cassandra and RabbitMQCQRS and Event Sourcing with Akka, Cassandra and RabbitMQ
CQRS and Event Sourcing with Akka, Cassandra and RabbitMQ
 
A pattern language for microservices (melbourne)
A pattern language for microservices (melbourne)A pattern language for microservices (melbourne)
A pattern language for microservices (melbourne)
 

Similar to NodeJS: the good parts? A skeptic’s view (jax jax2013)

NodeJS: the good parts? A skeptic’s view (devnexus2014)
NodeJS: the good parts? A skeptic’s view (devnexus2014)NodeJS: the good parts? A skeptic’s view (devnexus2014)
NodeJS: the good parts? A skeptic’s view (devnexus2014)Chris Richardson
 
apidays LIVE Australia - Building distributed systems on the shoulders of gia...
apidays LIVE Australia - Building distributed systems on the shoulders of gia...apidays LIVE Australia - Building distributed systems on the shoulders of gia...
apidays LIVE Australia - Building distributed systems on the shoulders of gia...apidays
 
Consuming web services asynchronously with Futures and Rx Observables (svcc, ...
Consuming web services asynchronously with Futures and Rx Observables (svcc, ...Consuming web services asynchronously with Futures and Rx Observables (svcc, ...
Consuming web services asynchronously with Futures and Rx Observables (svcc, ...Chris Richardson
 
Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...Chris Richardson
 
NodeJS: the good parts? A skeptic’s view (oredev, oredev2013)
NodeJS: the good parts? A skeptic’s view (oredev, oredev2013)NodeJS: the good parts? A skeptic’s view (oredev, oredev2013)
NodeJS: the good parts? A skeptic’s view (oredev, oredev2013)Chris Richardson
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applicationsTom Croucher
 
Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Paco de la Cruz
 
Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016Ben Lesh
 
Cервер на Go для мобильной стратегии
Cервер на Go для мобильной стратегииCервер на Go для мобильной стратегии
Cервер на Go для мобильной стратегииArtem Kovardin
 
Node js introduction
Node js introductionNode js introduction
Node js introductionAlex Su
 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013Laurent_VB
 
Store and Process Big Data with Hadoop and Cassandra
Store and Process Big Data with Hadoop and CassandraStore and Process Big Data with Hadoop and Cassandra
Store and Process Big Data with Hadoop and CassandraDeependra Ariyadewa
 
Expert JavaScript tricks of the masters
Expert JavaScript  tricks of the mastersExpert JavaScript  tricks of the masters
Expert JavaScript tricks of the mastersAra Pehlivanian
 
Joe Walker Interactivewebsites Cometand Dwr
Joe Walker Interactivewebsites Cometand DwrJoe Walker Interactivewebsites Cometand Dwr
Joe Walker Interactivewebsites Cometand Dwrdeimos
 
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)Brian Sam-Bodden
 
Spring data iii
Spring data iiiSpring data iii
Spring data iii명철 강
 
CouchDB Mobile - From Couch to 5K in 1 Hour
CouchDB Mobile - From Couch to 5K in 1 HourCouchDB Mobile - From Couch to 5K in 1 Hour
CouchDB Mobile - From Couch to 5K in 1 HourPeter Friese
 
NodeJS: the good parts? A skeptic’s view (jmaghreb, jmaghreb2013)
NodeJS: the good parts? A skeptic’s view (jmaghreb, jmaghreb2013)NodeJS: the good parts? A skeptic’s view (jmaghreb, jmaghreb2013)
NodeJS: the good parts? A skeptic’s view (jmaghreb, jmaghreb2013)Chris Richardson
 
NoSQL and JavaScript: a Love Story
NoSQL and JavaScript: a Love StoryNoSQL and JavaScript: a Love Story
NoSQL and JavaScript: a Love StoryAlexandre Morgaut
 

Similar to NodeJS: the good parts? A skeptic’s view (jax jax2013) (20)

NodeJS: the good parts? A skeptic’s view (devnexus2014)
NodeJS: the good parts? A skeptic’s view (devnexus2014)NodeJS: the good parts? A skeptic’s view (devnexus2014)
NodeJS: the good parts? A skeptic’s view (devnexus2014)
 
apidays LIVE Australia - Building distributed systems on the shoulders of gia...
apidays LIVE Australia - Building distributed systems on the shoulders of gia...apidays LIVE Australia - Building distributed systems on the shoulders of gia...
apidays LIVE Australia - Building distributed systems on the shoulders of gia...
 
Consuming web services asynchronously with Futures and Rx Observables (svcc, ...
Consuming web services asynchronously with Futures and Rx Observables (svcc, ...Consuming web services asynchronously with Futures and Rx Observables (svcc, ...
Consuming web services asynchronously with Futures and Rx Observables (svcc, ...
 
Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...
 
NodeJS: the good parts? A skeptic’s view (oredev, oredev2013)
NodeJS: the good parts? A skeptic’s view (oredev, oredev2013)NodeJS: the good parts? A skeptic’s view (oredev, oredev2013)
NodeJS: the good parts? A skeptic’s view (oredev, oredev2013)
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)
 
Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016Async Redux Actions With RxJS - React Rally 2016
Async Redux Actions With RxJS - React Rally 2016
 
Cервер на Go для мобильной стратегии
Cервер на Go для мобильной стратегииCервер на Go для мобильной стратегии
Cервер на Go для мобильной стратегии
 
Node js introduction
Node js introductionNode js introduction
Node js introduction
 
Developing web-apps like it's 2013
Developing web-apps like it's 2013Developing web-apps like it's 2013
Developing web-apps like it's 2013
 
Store and Process Big Data with Hadoop and Cassandra
Store and Process Big Data with Hadoop and CassandraStore and Process Big Data with Hadoop and Cassandra
Store and Process Big Data with Hadoop and Cassandra
 
Expert JavaScript tricks of the masters
Expert JavaScript  tricks of the mastersExpert JavaScript  tricks of the masters
Expert JavaScript tricks of the masters
 
Joe Walker Interactivewebsites Cometand Dwr
Joe Walker Interactivewebsites Cometand DwrJoe Walker Interactivewebsites Cometand Dwr
Joe Walker Interactivewebsites Cometand Dwr
 
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
 
Spring data iii
Spring data iiiSpring data iii
Spring data iii
 
NodeJS
NodeJSNodeJS
NodeJS
 
CouchDB Mobile - From Couch to 5K in 1 Hour
CouchDB Mobile - From Couch to 5K in 1 HourCouchDB Mobile - From Couch to 5K in 1 Hour
CouchDB Mobile - From Couch to 5K in 1 Hour
 
NodeJS: the good parts? A skeptic’s view (jmaghreb, jmaghreb2013)
NodeJS: the good parts? A skeptic’s view (jmaghreb, jmaghreb2013)NodeJS: the good parts? A skeptic’s view (jmaghreb, jmaghreb2013)
NodeJS: the good parts? A skeptic’s view (jmaghreb, jmaghreb2013)
 
NoSQL and JavaScript: a Love Story
NoSQL and JavaScript: a Love StoryNoSQL and JavaScript: a Love Story
NoSQL and JavaScript: a Love Story
 

More from Chris Richardson

The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?Chris Richardson
 
More the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternMore the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternChris Richardson
 
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...Chris Richardson
 
Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Chris Richardson
 
Dark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsDark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsChris Richardson
 
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfScenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfChris Richardson
 
Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Chris Richardson
 
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...Chris Richardson
 
Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Chris Richardson
 
A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 Chris Richardson
 
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureQConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureChris Richardson
 
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Chris Richardson
 
Designing loosely coupled services
Designing loosely coupled servicesDesigning loosely coupled services
Designing loosely coupled servicesChris Richardson
 
Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Chris Richardson
 
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...Chris Richardson
 
Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Chris Richardson
 
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...Chris Richardson
 
Overview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationOverview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationChris Richardson
 
An overview of the Eventuate Platform
An overview of the Eventuate PlatformAn overview of the Eventuate Platform
An overview of the Eventuate PlatformChris Richardson
 
#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolithChris Richardson
 

More from Chris Richardson (20)

The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?The microservice architecture: what, why, when and how?
The microservice architecture: what, why, when and how?
 
More the merrier: a microservices anti-pattern
More the merrier: a microservices anti-patternMore the merrier: a microservices anti-pattern
More the merrier: a microservices anti-pattern
 
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
YOW London - Considering Migrating a Monolith to Microservices? A Dark Energy...
 
Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!Dark Energy, Dark Matter and the Microservices Patterns?!
Dark Energy, Dark Matter and the Microservices Patterns?!
 
Dark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patternsDark energy, dark matter and microservice architecture collaboration patterns
Dark energy, dark matter and microservice architecture collaboration patterns
 
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdfScenarios_and_Architecture_SkillsMatter_April_2022.pdf
Scenarios_and_Architecture_SkillsMatter_April_2022.pdf
 
Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions Using patterns and pattern languages to make better architectural decisions
Using patterns and pattern languages to make better architectural decisions
 
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
iSAQB gathering 2021 keynote - Architectural patterns for rapid, reliable, fr...
 
Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...Events to the rescue: solving distributed data problems in a microservice arc...
Events to the rescue: solving distributed data problems in a microservice arc...
 
A pattern language for microservices - June 2021
A pattern language for microservices - June 2021 A pattern language for microservices - June 2021
A pattern language for microservices - June 2021
 
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice ArchitectureQConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
QConPlus 2021: Minimizing Design Time Coupling in a Microservice Architecture
 
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
Mucon 2021 - Dark energy, dark matter: imperfect metaphors for designing micr...
 
Designing loosely coupled services
Designing loosely coupled servicesDesigning loosely coupled services
Designing loosely coupled services
 
Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)Microservices - an architecture that enables DevOps (T Systems DevOps day)
Microservices - an architecture that enables DevOps (T Systems DevOps day)
 
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
DDD SoCal: Decompose your monolith: Ten principles for refactoring a monolith...
 
Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...Decompose your monolith: Six principles for refactoring a monolith to microse...
Decompose your monolith: Six principles for refactoring a monolith to microse...
 
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
TDC2020 - The microservice architecture: enabling rapid, reliable, frequent a...
 
Overview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders applicationOverview of the Eventuate Tram Customers and Orders application
Overview of the Eventuate Tram Customers and Orders application
 
An overview of the Eventuate Platform
An overview of the Eventuate PlatformAn overview of the Eventuate Platform
An overview of the Eventuate Platform
 
#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith#DevNexus202 Decompose your monolith
#DevNexus202 Decompose your monolith
 

Recently uploaded

UiPath Studio Web workshop Series - Day 3
UiPath Studio Web workshop Series - Day 3UiPath Studio Web workshop Series - Day 3
UiPath Studio Web workshop Series - Day 3DianaGray10
 
My key hands-on projects in Quantum, and QAI
My key hands-on projects in Quantum, and QAIMy key hands-on projects in Quantum, and QAI
My key hands-on projects in Quantum, and QAIVijayananda Mohire
 
UiPath Studio Web workshop series - Day 1
UiPath Studio Web workshop series  - Day 1UiPath Studio Web workshop series  - Day 1
UiPath Studio Web workshop series - Day 1DianaGray10
 
Technical SEO for Improved Accessibility WTS FEST
Technical SEO for Improved Accessibility  WTS FESTTechnical SEO for Improved Accessibility  WTS FEST
Technical SEO for Improved Accessibility WTS FESTBillieHyde
 
How to release an Open Source Dataweave Library
How to release an Open Source Dataweave LibraryHow to release an Open Source Dataweave Library
How to release an Open Source Dataweave Libraryshyamraj55
 
Oracle Database 23c Security New Features.pptx
Oracle Database 23c Security New Features.pptxOracle Database 23c Security New Features.pptx
Oracle Database 23c Security New Features.pptxSatishbabu Gunukula
 
3 Pitfalls Everyone Should Avoid with Cloud Data
3 Pitfalls Everyone Should Avoid with Cloud Data3 Pitfalls Everyone Should Avoid with Cloud Data
3 Pitfalls Everyone Should Avoid with Cloud DataEric D. Schabell
 
IT Service Management (ITSM) Best Practices for Advanced Computing
IT Service Management (ITSM) Best Practices for Advanced ComputingIT Service Management (ITSM) Best Practices for Advanced Computing
IT Service Management (ITSM) Best Practices for Advanced ComputingMAGNIntelligence
 
Patch notes explaining DISARM Version 1.4 update
Patch notes explaining DISARM Version 1.4 updatePatch notes explaining DISARM Version 1.4 update
Patch notes explaining DISARM Version 1.4 updateadam112203
 
Trailblazer Community - Flows Workshop (Session 2)
Trailblazer Community - Flows Workshop (Session 2)Trailblazer Community - Flows Workshop (Session 2)
Trailblazer Community - Flows Workshop (Session 2)Muhammad Tiham Siddiqui
 
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024Alkin Tezuysal
 
Keep Your Finger on the Pulse of Your Building's Performance with IES Live
Keep Your Finger on the Pulse of Your Building's Performance with IES LiveKeep Your Finger on the Pulse of Your Building's Performance with IES Live
Keep Your Finger on the Pulse of Your Building's Performance with IES LiveIES VE
 
.NET 8 ChatBot with Azure OpenAI Services.pptx
.NET 8 ChatBot with Azure OpenAI Services.pptx.NET 8 ChatBot with Azure OpenAI Services.pptx
.NET 8 ChatBot with Azure OpenAI Services.pptxHansamali Gamage
 
Explore the UiPath Community and ways you can benefit on your journey to auto...
Explore the UiPath Community and ways you can benefit on your journey to auto...Explore the UiPath Community and ways you can benefit on your journey to auto...
Explore the UiPath Community and ways you can benefit on your journey to auto...DianaGray10
 
How to become a GDSC Lead GDSC MI AOE.pptx
How to become a GDSC Lead GDSC MI AOE.pptxHow to become a GDSC Lead GDSC MI AOE.pptx
How to become a GDSC Lead GDSC MI AOE.pptxKaustubhBhavsar6
 
Introduction - IPLOOK NETWORKS CO., LTD.
Introduction - IPLOOK NETWORKS CO., LTD.Introduction - IPLOOK NETWORKS CO., LTD.
Introduction - IPLOOK NETWORKS CO., LTD.IPLOOK Networks
 
Extra-120324-Visite-Entreprise-icare.pdf
Extra-120324-Visite-Entreprise-icare.pdfExtra-120324-Visite-Entreprise-icare.pdf
Extra-120324-Visite-Entreprise-icare.pdfInfopole1
 
AI Workshops at Computers In Libraries 2024
AI Workshops at Computers In Libraries 2024AI Workshops at Computers In Libraries 2024
AI Workshops at Computers In Libraries 2024Brian Pichman
 
Automation Ops Series: Session 2 - Governance for UiPath projects
Automation Ops Series: Session 2 - Governance for UiPath projectsAutomation Ops Series: Session 2 - Governance for UiPath projects
Automation Ops Series: Session 2 - Governance for UiPath projectsDianaGray10
 

Recently uploaded (20)

UiPath Studio Web workshop Series - Day 3
UiPath Studio Web workshop Series - Day 3UiPath Studio Web workshop Series - Day 3
UiPath Studio Web workshop Series - Day 3
 
My key hands-on projects in Quantum, and QAI
My key hands-on projects in Quantum, and QAIMy key hands-on projects in Quantum, and QAI
My key hands-on projects in Quantum, and QAI
 
UiPath Studio Web workshop series - Day 1
UiPath Studio Web workshop series  - Day 1UiPath Studio Web workshop series  - Day 1
UiPath Studio Web workshop series - Day 1
 
Technical SEO for Improved Accessibility WTS FEST
Technical SEO for Improved Accessibility  WTS FESTTechnical SEO for Improved Accessibility  WTS FEST
Technical SEO for Improved Accessibility WTS FEST
 
How to release an Open Source Dataweave Library
How to release an Open Source Dataweave LibraryHow to release an Open Source Dataweave Library
How to release an Open Source Dataweave Library
 
Oracle Database 23c Security New Features.pptx
Oracle Database 23c Security New Features.pptxOracle Database 23c Security New Features.pptx
Oracle Database 23c Security New Features.pptx
 
3 Pitfalls Everyone Should Avoid with Cloud Data
3 Pitfalls Everyone Should Avoid with Cloud Data3 Pitfalls Everyone Should Avoid with Cloud Data
3 Pitfalls Everyone Should Avoid with Cloud Data
 
IT Service Management (ITSM) Best Practices for Advanced Computing
IT Service Management (ITSM) Best Practices for Advanced ComputingIT Service Management (ITSM) Best Practices for Advanced Computing
IT Service Management (ITSM) Best Practices for Advanced Computing
 
Patch notes explaining DISARM Version 1.4 update
Patch notes explaining DISARM Version 1.4 updatePatch notes explaining DISARM Version 1.4 update
Patch notes explaining DISARM Version 1.4 update
 
Trailblazer Community - Flows Workshop (Session 2)
Trailblazer Community - Flows Workshop (Session 2)Trailblazer Community - Flows Workshop (Session 2)
Trailblazer Community - Flows Workshop (Session 2)
 
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
Design and Modeling for MySQL SCALE 21X Pasadena, CA Mar 2024
 
Keep Your Finger on the Pulse of Your Building's Performance with IES Live
Keep Your Finger on the Pulse of Your Building's Performance with IES LiveKeep Your Finger on the Pulse of Your Building's Performance with IES Live
Keep Your Finger on the Pulse of Your Building's Performance with IES Live
 
.NET 8 ChatBot with Azure OpenAI Services.pptx
.NET 8 ChatBot with Azure OpenAI Services.pptx.NET 8 ChatBot with Azure OpenAI Services.pptx
.NET 8 ChatBot with Azure OpenAI Services.pptx
 
Explore the UiPath Community and ways you can benefit on your journey to auto...
Explore the UiPath Community and ways you can benefit on your journey to auto...Explore the UiPath Community and ways you can benefit on your journey to auto...
Explore the UiPath Community and ways you can benefit on your journey to auto...
 
SheDev 2024
SheDev 2024SheDev 2024
SheDev 2024
 
How to become a GDSC Lead GDSC MI AOE.pptx
How to become a GDSC Lead GDSC MI AOE.pptxHow to become a GDSC Lead GDSC MI AOE.pptx
How to become a GDSC Lead GDSC MI AOE.pptx
 
Introduction - IPLOOK NETWORKS CO., LTD.
Introduction - IPLOOK NETWORKS CO., LTD.Introduction - IPLOOK NETWORKS CO., LTD.
Introduction - IPLOOK NETWORKS CO., LTD.
 
Extra-120324-Visite-Entreprise-icare.pdf
Extra-120324-Visite-Entreprise-icare.pdfExtra-120324-Visite-Entreprise-icare.pdf
Extra-120324-Visite-Entreprise-icare.pdf
 
AI Workshops at Computers In Libraries 2024
AI Workshops at Computers In Libraries 2024AI Workshops at Computers In Libraries 2024
AI Workshops at Computers In Libraries 2024
 
Automation Ops Series: Session 2 - Governance for UiPath projects
Automation Ops Series: Session 2 - Governance for UiPath projectsAutomation Ops Series: Session 2 - Governance for UiPath projects
Automation Ops Series: Session 2 - Governance for UiPath projects
 

NodeJS: the good parts? A skeptic’s view (jax jax2013)

  • 1. @crichardson NodeJS: the good parts? A skeptic’s view Chris Richardson Author of POJOs in Action Founder of the original CloudFoundry.com @crichardson chris.richardson@springsource.com http://plainoldobjects.com
  • 2. @crichardson Presentation goal How a curmudgeonly server-side Java developer discovered an appreciation for NodeJS and JavaScript
  • 8. @crichardson vmc push About-Chris Developer Advocate Signup at http://cloudfoundry.com
  • 9. @crichardson Agenda Overview of NodeJS Building a front-end server with NodeJS Taming tangled asynchronous code with promises
  • 12. @crichardson NodeJS Hello World app.js $ node app.js $ curl http://localhost:1337 http://nodejs.org/ Load a module request handler
  • 15. @crichardson Dynamic, weakly-typed Dynamic: Types are associated with values - not variables Define new program elements at runtime Weakly typed: Leave out arguments to methods Access non-existent object properties Weird implicit conversions: 99 == “99”! truthy and falsy values Comprehensive tests are essential
  • 16. @crichardson JavaScript is object-oriented > var fred = {name: “Fred”, gender: “Male”}; undefined > fred.name “Fred” > console.log("reading age=" + fred.age); reading age=undefined undefined > fred.age = 99; 99 > fred { name: 'Fred', gender: 'Male', age: 99 } > delete fred.age true > fred { name: 'Fred', gender: 'Male' } Unordered key-value pairs Keys = properties Add property Delete property
  • 17. @crichardson JavaScript “classes” function Person(name) { this.name = name; } Person.prototype.sayHello = function () { console.log("Hello " + this.name); }; var chris = new Person("Chris"); chris.sayHello(); Looks like a constructor?!? What’s that?!?! This Java-like syntax is a mess because JavaScript isn’t class based Looks familiar
  • 18. @crichardson overrides JavaScript is a prototypal language __proto__ a 99 __proto__ a 100 b 200 inherited Prototype X Y
  • 19. @crichardson Prototypal code $ node > var person = {}; undefined > person.sayHello = function () { console.log("Hello " + this.name); }; [Function] > var chris = Object.create(person, {name: {value: "Chris"}}); undefined > var sarah = Object.create(person, {name: {value: "Sarah"}}); undefined > chris.sayHello(); Hello Chris undefined > sarah.sayHello(); Hello Sarah undefined > chris.sayHello = function () { console.log("Hello mate: " + this.name); }; [Function] > chris.sayHello(); Hello mate: Chris undefined Not defined here prototype properties
  • 20. @crichardson JavaScript is Functional function makeGenerator(nextFunction) { var value = 0; return function() { var current = value; value = nextFunction(value); return current; }; } var inc = makeGenerator(function (x) {return x + 1; }); > inc() 0 > inc() 1 Pass function as an argument Return a function closure
  • 21. @crichardson Partial function application > var join = require("path").join; undefined > join("/x", "y") '/x/y' > var withinx = join.bind(undefined, "/x"); undefined > withinx("y"); '/x/y' > partially apply join
  • 22. @crichardson Created in a hurry with the goal of looking like Java The ‘Java...’ name creates expectations that it can’t satisfy Fake classes: Hides prototypes BUT still seems weird global namespace scope of vars is confusing Missing return statement = confusion ‘function’ is really verbose ‘this’ is dynamically scoped
  • 23. @crichardson JavaScript is the only way to get things done in the browser
  • 24. @crichardson Stockholm syndrome “Stockholm syndrome ... is a psychological phenomenon in which hostages ... have positive feelings toward their captors, sometimes to the point of defending them...” http://en.wikipedia.org/wiki/Stockholm_syndrome
  • 25. @crichardson Martin Fowler once said: "...I'm one of those who despairs that a language with such deep flaws plays such an important role in computation. Still the consequence of this is that we must take javascript seriously as a first-class language and concentrate on how to limit the damage its flaws cause. ...." http://martinfowler.com/bliki/gotoAarhus2012.html
  • 27. @crichardson Use a better language that compiles to JavaScript TypeScript Typed parameters and fields Classes and interfaces (dynamic structural typing) Dart Class-based OO Optional static typing Bidirectional binding with DOM elements
  • 28. @crichardson CoffeeScript Hello World http = require('http') class HttpRequestHandler constructor: (@message) -> handle: (req, res) => res.writeHead(200, {'Content-Type': 'text/plain'}) res.end(@message + 'n') handler = new HttpRequestHandler "Hi There from CoffeeScript" server = http.createServer(handler.handle) server.listen(1338, '127.0.0.1') console.log('Server running at http://127.0.0.1:1338/') Classes :-) Bound method
  • 30. @crichardson About the Reactor pattern Defined by Doug Schmidt in 1995 Pattern for writing scalable servers Alternative to thread-per-connection model Single threaded event loop dispatches events on handles (e.g. sockets, file descriptors) to event handlers
  • 31. @crichardson Reactor pattern structure Event Handler handle_event(type) get_handle() Initiation Dispatcher handle_events() register_handler(h) select(handlers) for each h in handlers h.handle_event(type) end loop handle Synchronous Event Demultiplexer select() owns notifies uses handlers
  • 32. @crichardson Benefits: Separation of concerns - event handlers separated from low-level mechanism More efficient - no thread context switching Simplified concurrency - single threaded
  • 33. @crichardson Drawbacks: Non-pre-emptive - handlers can’t block/take a long time Difficult to understand and debug - inverted flow of control
  • 34. @crichardson NodeJS event loop implements the Reactor pattern
  • 35. @crichardson Application code Event-driven architecture NodeJS event loop Basic networking/file-system/etc. HTTP DB driver ... Event listener Callback function One time events Recurring events
  • 36. @crichardson Getting notified: Callback example var fs = require("fs"); function statFile(path) { fs.stat(path, function (err, stat) { if (err) { console.log("Stat failed: " + path, err); throw err; } console.log("stat result=" + path, stat); }); }; By convention: first param is error object By convention: Last arg is a callback Callbacks are good for one time notifications
  • 37. @crichardson Getting notified: event listeners EventEmitter class - inherit or use Listener registration methods: on(eventName, listener) once(eventName, listener) Emitting events emit(eventName, args...) ‘error’ event = special case: no listener print stack trace and exit! Good for recurring events
  • 38. @crichardson Event listener example var fs = require("fs"); var readStream = fs.createReadStream("events.js", {encoding: "utf-8"}); // ReadStream << ReadableStream << EventEmitter readStream.on('open', function (fd) { console.log("opened with fd=", fd); }); // Node v0.10 has readable instead: this is deprecated readStream.on('data', function (data) { console.log("data=", data); }); Register listener Register listener
  • 39. @crichardson Callback hell function times2(x, callback) { setTimeout(function () { callback(x * 2)}, 500); } function plus3(x, callback) { setTimeout(function (){ callback(x + 3)}, 500); } function displayResult(z) { console.log("The result is=", z); } function plus3AndThenTimes2(x, callback) { plus3(x, function (y) { times2(y, callback) }) } plus3AndThenTimes2(10, displayResults); function sum(a, b, callback) { setTimeout(function () { callback(a + b); }, 500); } function plus3PlusTimes2(x, callback) { var p3, t2; function perhapsDone() { if (p3 & t2) sum(p3, t2, callback); }; plus3(x, function (y) { p3 = y; perhapsDone(); }); times2(x, function (y) { t2 = y; perhapsDone(); }); } plus3PlusTimes2(10, displayResult); times2(plus3(x)) times2(x) + plus3(x)
  • 40. @crichardson Long running computations Long running computation blocks event loop for other requests Need to run outside of main event loop Options: Community: web workers threads Built-in: NodeJS child processes
  • 41. @crichardson Using child processes var child = require('child_process').fork('child.js'); function sayHelloToChild() { child.send({hello: "child"}); } setTimeout(sayHelloToChild, 1000); child.on('message', function(m) { console.log('parent received:', m); }); function kill() { child.kill(); } setTimeout(kill, 2000); process.on('message', function (m) { console.log("child received message=", m); process.send({ihateyou: "you ruined my life"}) }); parent.js child.js Create child process Send message to child
  • 43. Core built-in modules Basic networking HTTP(S) Filesystem Events Timers ...
  • 44. @crichardson Thousands of community developed modules https://npmjs.org/ web frameworks, SQL/NoSQL database, drivers, messaging, utilities...
  • 45. @crichardson What’s a module? One or more JavaScript files Optional native code: Compiled during installation JavaScript != systems programming language Package.json - metadata including dependencies exports.sayHello = function () { console.log(“Hello”); } foo.js
  • 46. @crichardson Easy to install $ npm install package-name
  • 47. @crichardson Easy to use var http = require(“http”) var server = http.createServer... Core module OR Path to file OR module in node_modules Module’s exports
  • 48. @crichardson Developing with NodeJS modules Core modules Community modules Your modules Application code
  • 49. @crichardson Lots of modules BUT... Variable quality Multiple incomplete MySQL drivers, e.g. without connection pooling! Often abandoned ...
  • 50. @crichardson To summarize NodeJS JavaScript Reactor patternModules Flawed and misunderstood Scalable yet costly and often unnecessary Rich but variable quality
  • 51. @crichardson Alternative technologies Atmosphere - portable event delivery Netty - asynchronous I/O Vert.x SpringSource’s Reactor project ...
  • 52. @crichardson So why care about NodeJS? Easy to write scalable network services Easy to push events to the browser Easy to get (small) stuff done It has a role to play in modern application architecture
  • 53. @crichardson Evolving from a monolithic architecture.... WAR Shipping Service Accounting Service Inventory Service StoreFrontUI
  • 54. @crichardson ... to a micro-service architecture Store front web application shipping web application inventory web application Accounting Service StoreFrontUI accounting web application Shipping Service Inventory Service
  • 56. @crichardson Browser Web application RESTful EndpointsModel View Controller ...Presentation layer evolution JSON-REST HTML 5 - JavaScript No elaborate, server-side web framework required Event publisher Events Static content
  • 57. @crichardson NodeJS as an API gateway Browser Service 1 Service 2 Message Bus HTML 5/ Java Script Socket.io client Events RESTful WS Server application Socket.io server Node JS Service 3 RESTful WS
  • 58. @crichardson Agenda Overview of NodeJS Building a front-end server with NodeJS Taming tangled asynchronous code with promises
  • 60. @crichardson Using low-level APIs var http = require('http'), path = require('path'), mime = require('mime'), fs = require("fs"); var server = http.createServer(function (req, res) { var filePath; if (req.url == '/') { filePath = 'public/index.html'; } else { filePath = 'public' + req.url; } fs.exists(filePath, function (exists) { if (exists) { res.writeHead(200, {"content-type": mime.lookup(path.basename(filePath)) }); fs.createReadStream(filePath).pipe(res); } else { res.writeHead(404, {'Content-Type': 'text/plain'}); res.write('Error 404: resource not found.'); res.end(); } }); } ); server.listen(1337, '127.0.0.1'); console.log('Server running at http://127.0.0.1:1337/'); Uses file extension Cool!
  • 61. @crichardson Using the express web framework var express = require('express') , http = require('http') , app = express() , server = http.createServer(app) ; app.configure(function(){ app.use(express.static(__dirname + '/public')); }); server.listen(8081);
  • 63. @crichardson Implementing RESTful WS with Express var express = require('express'), http = require('http'), path = require('path'); var app = express(); var server = http.createServer(app); app.get('/portfolio/:userId', function (req, res) { var portfolio = retrievePortfolio(req.params.userId); res.json(portfolio); }); Easy URL routing and destructuring
  • 64. @crichardson Proxying to backend server express = require('express') request = require('request') app = express.createServer() proxyToBackend = (baseUrl) -> (req, res) -> callback = (error, response, body) -> console.log("error=", error) originRequest = request(baseUrl + req.url, callback) req.pipe(originRequest) originRequest.pipe(res) app.get('/restaurant/*', proxyToBackend('http://available-restaurant....com')) app.post('/orders', proxyToBackend('http://restaurant-management...com')) app.get('/orders', proxyToBackend(''http://restaurant-management...com')) Returns a request handler that proxies to baseUrl
  • 67. @crichardson Socket.io - Server side var express = require('express') , http = require('http') , app = express() , server = http.createServer(app) , io = require('socket.io').listen(server) ; app.configure(function(){ app.use(express.static(__dirname + '/public')); }); server.listen(8081); io.sockets.on('connection', function (socket) { var counter = 0; function tick() { counter = counter + 1; socket.emit('tick', counter); }; setInterval(tick, 1000); }); handle new connection Send tick event to browser every 1 sec initializes socket.io
  • 68. @crichardson Socket.io - client side using the knockout.js MVVM framework var socket = io.connect(location.hostname); function ClockModel() { self.ticker = ko.observable(1); socket.on('tick', function (data) { self.ticker(data); }); }; ko.applyBindings(new ClockModel()); <html> <body> The event is <span data-bind="text: ticker"></span> <script src="/socket.io/socket.io.js"></script> <script src="/knockout-2.0.0.js"></script> <script src="/clock.js"></script> </body> </html> clock.js Connect to socket.io Subscribe to tick event Bind to model Update model
  • 69. @crichardson Distributed NodeJS clock example Browser NodeJS NodeJS RabbitMQ ProducerConsumer socket.iosocket.io
  • 70. @crichardson AMQP Publisher var amqp = require('amqp'), amqpConnection = amqp.createConnection(...), tickTockExchange; function tick() { var message = { tick: Date.now() }; tickTockExchange.publish("tickTock", message, { mandatory: true, contentType: "text/plain" }); }; amqpConnection.on('ready', function () { tickTockExchange = amqpConnection.exchange("tickTock", options = {passive: false, type: 'fanout'}); tickTockExchange.on('open', function () { setInterval(tick, 1000) }); }); Connect to AMQP Ensure exchange exists Publish message Initialize timer
  • 71. @crichardson AMQP socket.iovar express = require('express') , http = require('http') , amqp = require(‘amqp’) ....; server.listen(8081); ... var amqpCon = amqp.createConnection(...); io.sockets.on('connection', function (socket) { function amqpMessageHandler(message, headers, deliveryInfo) { var m = JSON.parse(message.data.toString()); socket.emit(‘tick’, m); }; amqpCon.queue(“”, {}, function(queue) { queue.bind(“tickTock”, “”); queue.subscribe(amqpMessageHandler); }); }); Connect to AMQP queue Subscribe to AMQP queue Republish as socket.io event https://github.com/cer/nodejs-clock
  • 72. @crichardson Agenda Overview of NodeJS Building a front-end server with NodeJS Taming tangled asynchronous code with promises
  • 73. @crichardson Async code = callback hell Scenarios: Sequential: A B C Fork and join: A and B C Code quickly becomes very messy
  • 74. @crichardson Simplifying code with Promises (a.k.a. Futures) Functions return a promise - no callback parameter A promise represents an eventual outcome Use a library of functions for transforming and composing promises Promises/A+ specification - http://promises-aplus.github.io/promises-spec when.js (part of cujo.js by SpringSource) is a popular implementation
  • 75. @crichardson Taming callback hell 1 function times2(x) { var deferred = when.defer(); setTimeout(function () { deferred.resolve(x * 2)}, 500); return deferred.promise; } times2(plus3(x)) Create a deferred Return a promise Eventually supply a value function plus3AndThenTimes2(x) { return plus3(x).then(times2); } plus3AndThenTimes2(10). then(displayResult); Transform value in promise function plus3(x) { var deferred = when.defer(); setTimeout(function () { deferred.resolve(x + 3) }, 500); return deferred.promise; } Simpler, almost synchronous-style code
  • 76. @crichardson Taming callback hell 2 function sum(a, b) { var deferred = when.defer(); setTimeout(function () { deferred.resolve(a + b); }, 500); return deferred.promise; } function plus3PlusTimes2(x) { var p3 = plus3(x), t2 = times2(x); return when.join(p3, t2).spread(sum); } plus3PlusTimes2(10).then(displayResult); times2(x) + plus3(x) Combine results of two promises Call with array elements as arguments
  • 77. @crichardson Calling non-promise code var deferred = when.defer(); fs.stat(path, function (err, statInfo) { if (err) deferred.reject(err); else deferred.resolve(statInfo); } var promise = deferred.promise; var nodefn = require("when/node/function"); var promise = nodefn.call(fs.stat, path) Hides boilerplate code
  • 78. @crichardson Filesystem scanner example Read contents of directory Use stat to determine if directory or file Recurse on directories Merge the results
  • 79. @crichardson Read contents of directory function findFilesInDir(dir) { var directoryContents = nodefn.call(self.fs.readdir, dir); ... } Returns promise containing an array of file names
  • 80. @crichardson Create absolute paths function findFilesInDir(dir) { var directoryContents = ... var toAbsolute = join.bind(undefined, dir) var absolutePaths = when.map(directoryContents, toAbsolute); ... } Partially apply join()
  • 81. @crichardson Use stat to determine if directory or file function findFilesInDir(dir) { var directoryContents = ... var absolutePaths = ... var statTasks = when.map(absolutePaths, makeStatTask); var statResults = parallel(statTasks); ... } function makeStatTask(path) { return function () { function makeStatInfo(stats) { return {path: path, isdir: stats.isDirectory(), ctime: stats.ctime}; } return nodefn.call(self.fs.stat, path).then(makeStatInfo); }; } Execute stats in parallel
  • 82. @crichardson Recurse on directories function findFilesInDir(dir) { ... var statResults = ...; var listOfListsOfFiles = when.map(statResults, processStatInfo); ... } function processStatInfo(statInfo) { if (statInfo.isdir) { return findFilesInDir(statInfo.path); } else { return [statInfo.path]; } } Map each stat result to a list of files
  • 83. @crichardson Flatten array of arrays of file paths function findFilesInDir(dir) { ... var listOfListsOfFiles = ...; return when.reduce(listOfListsOfFiles, concatenateLists, []); } function concatenateLists(currentResult, value, index, total) { return currentResult.concat(value); }
  • 84. @crichardson Summary JavaScript is a very flawed language The asynchronous model is often unnecessary; very constraining; and adds complexity BUT despite those problems Today, NodeJS is remarkably useful for building network- focussed components