SlideShare a Scribd company logo
1 of 70
Download to read offline
Asynchronous 
programming 
done right. 
Without race conditions ..ions ..io on 
..ns ditions. 
by Piotr Pelczar (Athlan)
About me 
Piotr Pelczar 
Freelancer for 8yrs 
PHP, Node.js, Java/Groovy 
Zend Certified Engineer 
IPIJ, Startups
Stay in touch 
athlan.pl 
me@athlan.pl 
facebook.com/piotr.pelczar 
github.com/athlan 
slideshare.net/piotrpelczar 
linkedin.com/in/ppelczar
Asynchronous 
programming 
Asynchronous actions are actions executed in a non-blocking 
scheme, allowing the main program flow to continue processing.
How software lives in 
hardware? 
Operating systems are process based 
Each process has assigned processor, registers, memory
How software lives in 
hardware? 
Process paralelism using threads (thread pools) 
Switching processor over processes/threads causes context 
switching
1. context switching = wasting time
Sync programming 
In trivial, sequential approach 
Each operation is executed sequentially: 
O(t) > O(t+1) 
if O(t) stucks, O(t+1) waits...
Sync programming
This is cool, software flow is predictible 
But not in high throughput I/O 
I/O costs because of waiting time...
High throughput I/O 
High throughput I/O doesn't mean: 
Memory operations 
Fast single-thread computing
High throughput I/O 
High throughput I/O means: 
HTTP requests 
Database connections 
Queue system dispatching 
HDD operations
2. Avoid I/O blocking
2. Avoid I/O blocking
Single-threaded, event loop 
model 
Imagine a man, who has a task: 
Walk around 
When bucket is full of water, just pour another bucket 
Go to next bucket
There is no sequences 
In async programming, results appears in no sequences 
operation1(); // will output "operation1 finished." 
operation2(); // will output "operation2 finished." 
operation3(); // will output "operation3 finished."
There is no sequences 
operation1() would be 
var amqp = require("amqp") 
var eventbus = amqp.createConnection(); 
console.log("AMQP connecting..."); 
eventbus.on("ready", function() { 
console.log("AMQP connected..."); 
callback(); 
return; 
});
There is no sequences 
operation2() would be 
var redis = require("redis") 
var conn = redis.createClient(port, host, options); 
console.log("Redis connecting..."); 
conn.auth(pass, function(err) { 
if(err) 
console.log("Redis failed..."); 
else 
console.log("Redis connected..."); 
callback(); 
return; 
});
There is no sequences 
operation3() would be 
var mongojs = require("mongojs"); 
console.log("Mongo connecting..."); 
var conn = mongojs.connect(connectionString); // blocking operation 
console.log("Mongo connected..."); 
callback(); 
return;
There is no sequences 
Expectations? 
AMQP connecting... // operation1() 
AMQP connected... // operation1() 
Redis connecting... // operation2() 
Redis failed... // operation2() 
Mongo connecting... // operation3(), blocking 
Mongo connected... // operation3()
There is no sequences 
Expectations?
There is no sequences 
The result: 
AMQP connecting... // operation1() 
Redis connecting... // operation2() 
Mongo connecting... // operation3(), blocking 
Mongo connected... // operation3() 
Redis failed... // operation2() 
AMQP connected... // operation1()
There is no sequences
So... what functions 
returns? 
You can perform future tasks in function, so what will be 
returned? 
value123 will be returned, 
function my_function() { 
operation1(); 
operation2(); 
operation3(); 
return "value123"; 
} 
just after blocking code, without waiting for non-blocking.
Assume: Functions does 
NOT returns values 
The function block is executed immedietally from top to bottom. 
You cannot rely to return value, because it is useless.
Callbacks 
Callback is the reference to function. 
var callbackFunction = function(result) { 
console.log("Result: %s", result) 
} 
When operation is done, the callback function is executed. 
callbackFunction("test1") // "Result: test1" will be printed out
Callbacks 
If callbackFunction is a variable (value = reference), 
so can be passed it via function argument. 
var callbackFunction = function() { ... } 
someOtherFunction(callbackFunction); 
function someOtherFunction(callback) { 
callback(); // execute function from argument 
}
Callbacks 
Functions can be defined as anonymous (closures) 
function someOtherFunction(callback) { 
var arg1 = "test"; 
callback(arg1); // execute function from argument 
} 
someOtherFunction(function(arg1) { 
console.log('done... %s', arg1); 
})
Callbacks can be nested 
Nesting callbacks makes code unreadeable: 
var amqp = require('amqp'); 
var connection = amqp.createConnection(); 
connection.on('ready', function() { 
connection.exchange("ex1", function(exchange) { 
connection.queue('queue1', function(q) { 
q.bind(exchange, 'r1'); 
q.subscribe(function(json, headers, info, m) { 
console.log("msg: " + JSON.stringify(json)); 
}); 
}); 
}); 
});
Callbacks can be nested 
Nesting callbacks makes code unreadeable: 
var amqp = require('amqp'); 
var connection = amqp.createConnection(); 
connection.on('ready', function() { 
connection.exchange("ex1", function(exchange) { 
connection.queue('queue1', function(q) { 
q.bind(exchange, 'r1'); 
q.subscribe(function(json, headers, info, m) { 
console.log("msg: " + JSON.stringify(json)); 
table.update(select, data, function() { 
table.find(select, function(err, rows) { 
// inserted rows... 
} 
}); 
}); 
}); 
}); 
});
Asynchronous control flows 
Promise design pattern 
Libraries that manages callbacks references
Promise design pattern 
1. Client fires function that will return result in the future 
in the future, so it is a promise 
2. Function returns promise object immedietaly 
before non-blocking operations 
3. Client registers callbacks 
4. Callbacks will be fired in the future, when task is done 
var resultPromise = loader.loadData(sourceFile) 
resultPromise(function success(data) { 
// this function will be called while operation will succeed 
}, function error(err) { 
// on fail 
})
Promise design pattern 
1. Create deferred object 
2. Return def.promise 
3. Call resolve() or reject() 
var loadData = function(sourceFile) { 
var def = deferred() 
, proc = process.spawn('java', ['-jar', 'loadData.jar', sourceFile]) 
var commandProcessBuff = null 
, commandProcessBuffError = null; 
proc.stdout.on('data', function (data) { commandProcessBuff += data }) 
proc.stderr.on('data', function (data) { commandProcessBuffError += data }) 
proc.on('close', function (code) { 
if(null !== commandProcessBuffError) 
def.reject(commandProcessBuffError) 
else 
def.resolve(commandProcessBuff) 
}) 
return def.promise 
}
Promise design pattern
Async Node.js library 
Provides control flows like: 
Sequences (series) 
Waterfalls (sequences with parameters passing) 
Parallel (with limit) 
Some/every conditions 
While/until 
Queue
Async Node.js library 
Series
Async Node.js library 
Series 
async.series([ 
function(callback) { 
// operation1 
}, 
function(callback) { 
// operation2 
}, 
function(callback) { 
// operation3 
} 
], function() { 
console.log('all operations done') 
})
Async Node.js library 
Parallel 
async.parallel([ 
function(callback) { 
// operation1 
}, 
function(callback) { 
// operation2 
}, 
function(callback) { 
// operation3 
} 
], function() { 
console.log('all operations done') 
})
Async Node.js library 
Parallel limit
Async Node.js library 
Parallel limit 
var tasks = [ 
function(callback) { 
// operation1 
}, 
function(callback) { 
// operation2 
}, 
// ... 
] 
async.parallelLimit(tasks, 2, function() { 
console.log('all operations done') 
})
Async Node.js library 
Waterfall 
async.waterfall([ 
function(callback) { 
// operation1 
callback(null, arg1, arg2) 
}, 
function(arg1, arg2, callback) { 
// operation2 
callback(null, foo, bar) 
}, 
function(foo, bar, callback) { 
// operation3 
} 
], function() { 
console.log('all operations done') 
})
Async Node.js library 
Whilst 
async.doWhilst( 
function(done) { 
// operation1 
done(null, arg1, arg2) 
}, 
function() { 
return pages < limit 
} 
], function() { 
console.log('done') 
})
Asynchronous 
programming traps 
Dealing with callbacks may be tricky. Keep your code clean.
Unnamed callbacks 
Keep your code clean, don't name callback function callback 
function doSomething(callback) { 
return callback; 
}
Unnamed callbacks 
function doSomething(callback) { 
doAnotherThing(function(callback2) { 
doYetAnotherThing(function(callback3) { 
return callback(); 
}) 
}) 
}
Unnamed callbacks 
Instead of this, name your callbacks 
function doSomething(done) { 
doAnotherThing(function(doneFetchingFromApi) { 
doYetAnotherThing(function(doneWritingToDatabase) { 
return done(); 
}) 
}) 
}
Double callbacks 
function doSomething(done) { 
doAnotherThing(function (err) { 
if (err) done(err); 
done(null, result); 
}); 
} 
Callback is fired twice!
Double callbacks 
Fix: Always prepend callback execution with return statement. 
function doSomething(done) { 
doAnotherThing(function (err) { 
if (err) 
return done(err); 
return done(null, result); 
}); 
} 
Normally, return ends function execution, why do not keep this 
rule while async.
Double callbacks 
Double callbacks are very hard to debug. 
The callback wrapper can be written and execute it only once. 
setTimeout(function() { 
done('a') 
}, 200) 
setTimeout(function() { 
done('b') 
}, 500)
Double callbacks 
var CallbackOnce = function(callback) { 
this.isFired = false 
this.callback = callback 
} 
CallbackOnce.prototype.create = function() { 
var delegate = this 
return function() { 
if(delegate.isFired) 
return 
delegate.isFired = true 
delegate.callback.apply(null, arguments) 
} 
}
Double callbacks 
obj1 = new CallbackOnce(done) 
// decorate callback 
safeDone = obj1.create() // safeDone() is proxy function that passes arguments 
setTimeout(function() { 
safeDone('a') // safe now... 
}, 200) 
setTimeout(function() { 
safeDone('b') // safe now... 
}, 500)
Unexpected callbacks 
Never fire callback until task is done. 
function doSomething(done) { 
doAnotherThing(function () { 
if (condition) { 
var result = null 
// prepare result... 
return done(result); 
} 
return done(null); 
}); 
} 
The ending return will be fired even if condition pass.
Unexpected callbacks 
Never fire callback until task is done. 
function doSomething(done) { 
doAnotherThing(function () { 
if (condition) { 
var result = null 
// prepare result... 
return done(result); 
} 
else { 
return done(null); 
} 
}); 
}
Unexpected callbacks 
Never use callback in try clause! 
function (callback) { 
another_function(function (err, some_data) { 
if (err) 
return callback(err); 
try { 
callback(null, JSON.parse(some_data)); // error here 
} catch(err) { 
callback(new Error(some_data + ' is not a valid JSON')); 
} 
}); 
} 
If callback throws an exception, then it is executed exactly twice!
Unexpected callbacks 
Never use callback in try clause! 
function (callback) { 
another_function(function (err, some_data) { 
if (err) 
return callback(err); 
try { 
var parsed = JSON.parse(some_data) 
} catch(err) { 
return callback(new Error(some_data + ' is not a valid JSON')); 
} 
callback(null, parsed); 
}); 
}
Unexpected callbacks 
Never use callback in try clause!
Take care of events 
Read docs carefully. Really. 
function doSomething(done) { 
var proc = process.spawn('java', ['-jar', 'loadData.jar', sourceFile]) 
var procBuff = ''; 
proc.stdout.on('data', function (data) { 
procBuff += data; 
}); 
// WAT?! 
proc.stderr.on('data', function (data) { 
done(new Error("An error occured: " + data)) 
}); 
proc.on('close', function (code) { 
done(null, procBuff); 
} 
}
Take care of events 
Read docs carefully. Really. 
function doSomething(done) { 
var proc = process.spawn('java', ['-jar', 'loadData.jar', sourceFile]) 
var procBuff = ''; 
var procBuffError = ''; 
proc.stdout.on('data', function (data) { 
procBuff += data; 
}); 
proc.stderr.on('data', function (data) { 
proc += data; 
}); 
proc.on('close', function (code) { 
if(code !== 0) { 
return done(new Error("An error occured: " + procBuffError)); 
} 
else { 
return done(null, procBuff) 
} 
} 
}
Unreadable and logs 
Keep in mind, that asynchronous logs will interweave 
There are not sequenced 
Or there will be same log strings
Unexpected callbacks 
Asynchronous logs will interweave
Unreadable and logs 
Logs without use context are useless... 
function getResults(keyword, done) { 
http.request(url, function(response) { 
console.log('Fetching from API') 
response.on('error', function(err) { 
console.log('API error') 
}) 
}); 
}
Unreadable and logs 
function getResults(keyword, done) { 
var logContext = { keyword: keyword } 
http.request(url, function(response) { 
console.log(logContext, 'Fetching from API') 
response.on('error', function(err) { 
console.log(logContext, 'API error') 
}) 
}); 
}
Unreadable and logs 
Centralize your logs - use logstash 
And make them searcheable - Elasticsearch + Kibana
Too many opened 
background-tasks 
While running parallel in order to satisfy first-better algorithm, 
others should be aborted
Too many opened 
background-tasks 
Provide cancellation API: 
var events = require('events') 
function getResults(keyword) { 
var def = deferred() 
var eventbus = new events.EventEmitter() 
var req = http.request(url, function(response) { 
var err = null 
, content = null 
res.on('data', function(chunk) { 
content += chunk; 
}); 
response.on('close', function() { 
if(err) 
return def.reject(err) 
else 
return def.resolve(content) 
}) 
response.on('error', function(err) { 
err += err 
}) 
});
Too many opened 
background-tasks 
Provide cancellation API: 
var response = getResults('test') 
response.result(function success() { 
// ... 
}, function error() { 
// ... 
}) 
// if we need 
response.events.emit('abort')
Everything runs in parallel except your code. 
When currently code is running, (not waiting for I/O descriptors) 
whole event loop is blocked.
THE END 
by Piotr Pelczar
Q&A 
by Piotr Pelczar

More Related Content

What's hot

$q and Promises in AngularJS
$q and Promises in AngularJS $q and Promises in AngularJS
$q and Promises in AngularJS a_sharif
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript PromisesTomasz Bak
 
Boom! Promises/A+ Was Born
Boom! Promises/A+ Was BornBoom! Promises/A+ Was Born
Boom! Promises/A+ Was BornDomenic Denicola
 
Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)xSawyer
 
Java Script Promise
Java Script PromiseJava Script Promise
Java Script PromiseAlok Guha
 
Practical JavaScript Promises
Practical JavaScript PromisesPractical JavaScript Promises
Practical JavaScript PromisesAsa Kusuma
 
Node.js: Continuation-Local-Storage and the Magic of AsyncListener
Node.js: Continuation-Local-Storage and the Magic of AsyncListenerNode.js: Continuation-Local-Storage and the Magic of AsyncListener
Node.js: Continuation-Local-Storage and the Magic of AsyncListenerIslam Sharabash
 
Containers & Dependency in Ember.js
Containers & Dependency in Ember.jsContainers & Dependency in Ember.js
Containers & Dependency in Ember.jsMatthew Beale
 
Avoiding callback hell with promises
Avoiding callback hell with promisesAvoiding callback hell with promises
Avoiding callback hell with promisesTorontoNodeJS
 
Any event intro
Any event introAny event intro
Any event introqiang
 
Getting Comfortable with JS Promises
Getting Comfortable with JS PromisesGetting Comfortable with JS Promises
Getting Comfortable with JS PromisesAsa Kusuma
 
Why Redux-Observable?
Why Redux-Observable?Why Redux-Observable?
Why Redux-Observable?Anna Su
 
Perl: Coro asynchronous
Perl: Coro asynchronous Perl: Coro asynchronous
Perl: Coro asynchronous Shmuel Fomberg
 
How to send gzipped requests with boto3
How to send gzipped requests with boto3How to send gzipped requests with boto3
How to send gzipped requests with boto3Luciano Mammino
 

What's hot (20)

$q and Promises in AngularJS
$q and Promises in AngularJS $q and Promises in AngularJS
$q and Promises in AngularJS
 
Promise pattern
Promise patternPromise pattern
Promise pattern
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Promises, Promises
Promises, PromisesPromises, Promises
Promises, Promises
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Boom! Promises/A+ Was Born
Boom! Promises/A+ Was BornBoom! Promises/A+ Was Born
Boom! Promises/A+ Was Born
 
Async Frontiers
Async FrontiersAsync Frontiers
Async Frontiers
 
Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous Programming FTW! 2 (with AnyEvent)
 
Java Script Promise
Java Script PromiseJava Script Promise
Java Script Promise
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
Practical JavaScript Promises
Practical JavaScript PromisesPractical JavaScript Promises
Practical JavaScript Promises
 
Node.js: Continuation-Local-Storage and the Magic of AsyncListener
Node.js: Continuation-Local-Storage and the Magic of AsyncListenerNode.js: Continuation-Local-Storage and the Magic of AsyncListener
Node.js: Continuation-Local-Storage and the Magic of AsyncListener
 
Containers & Dependency in Ember.js
Containers & Dependency in Ember.jsContainers & Dependency in Ember.js
Containers & Dependency in Ember.js
 
Avoiding callback hell with promises
Avoiding callback hell with promisesAvoiding callback hell with promises
Avoiding callback hell with promises
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
Any event intro
Any event introAny event intro
Any event intro
 
Getting Comfortable with JS Promises
Getting Comfortable with JS PromisesGetting Comfortable with JS Promises
Getting Comfortable with JS Promises
 
Why Redux-Observable?
Why Redux-Observable?Why Redux-Observable?
Why Redux-Observable?
 
Perl: Coro asynchronous
Perl: Coro asynchronous Perl: Coro asynchronous
Perl: Coro asynchronous
 
How to send gzipped requests with boto3
How to send gzipped requests with boto3How to send gzipped requests with boto3
How to send gzipped requests with boto3
 

Viewers also liked

Soluciones tecnológicas para REA
Soluciones tecnológicas para REASoluciones tecnológicas para REA
Soluciones tecnológicas para REARicardo Corai
 
Implementación Repositorio De Objetos De Aprendizajes Basado En
Implementación Repositorio De Objetos De Aprendizajes Basado EnImplementación Repositorio De Objetos De Aprendizajes Basado En
Implementación Repositorio De Objetos De Aprendizajes Basado Enf.cabrera1
 
What is Node.js used for: The 2015 Node.js Overview Report
What is Node.js used for: The 2015 Node.js Overview ReportWhat is Node.js used for: The 2015 Node.js Overview Report
What is Node.js used for: The 2015 Node.js Overview ReportGabor Nagy
 
Responsive Design
Responsive DesignResponsive Design
Responsive DesignMRMtech
 
Presentacion MoodleMoot 2014 Colombia - Integración Moodle con un Repositorio...
Presentacion MoodleMoot 2014 Colombia - Integración Moodle con un Repositorio...Presentacion MoodleMoot 2014 Colombia - Integración Moodle con un Repositorio...
Presentacion MoodleMoot 2014 Colombia - Integración Moodle con un Repositorio...Paola Amadeo
 
Stack Overflow - It's all about performance / Marco Cecconi (Stack Overflow)
Stack Overflow - It's all about performance / Marco Cecconi (Stack Overflow)Stack Overflow - It's all about performance / Marco Cecconi (Stack Overflow)
Stack Overflow - It's all about performance / Marco Cecconi (Stack Overflow)Ontico
 
Modern HTML & CSS Coding: Speed, Semantics & Structure
Modern HTML & CSS Coding: Speed, Semantics & StructureModern HTML & CSS Coding: Speed, Semantics & Structure
Modern HTML & CSS Coding: Speed, Semantics & StructureRaven Tools
 
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
 
StrongLoop Overview
StrongLoop OverviewStrongLoop Overview
StrongLoop OverviewShubhra Kar
 
Why Scala for Web 2.0?
Why Scala for Web 2.0?Why Scala for Web 2.0?
Why Scala for Web 2.0?Alex Payne
 
Html5 devconf nodejs_devops_shubhra
Html5 devconf nodejs_devops_shubhraHtml5 devconf nodejs_devops_shubhra
Html5 devconf nodejs_devops_shubhraShubhra Kar
 
Node.js Frameworks & Design Patterns Webinar
Node.js Frameworks & Design Patterns WebinarNode.js Frameworks & Design Patterns Webinar
Node.js Frameworks & Design Patterns WebinarShubhra Kar
 
Webstock 2010 - Stack Overflow: Building Social Software for the Anti-Social
Webstock 2010 - Stack Overflow: Building Social Software for the Anti-SocialWebstock 2010 - Stack Overflow: Building Social Software for the Anti-Social
Webstock 2010 - Stack Overflow: Building Social Software for the Anti-Socialcodinghorror
 
Toronto node js_meetup
Toronto node js_meetupToronto node js_meetup
Toronto node js_meetupShubhra Kar
 
Introducing the New DSpace User Interface
Introducing the New DSpace User InterfaceIntroducing the New DSpace User Interface
Introducing the New DSpace User InterfaceTim Donohue
 
Stack Overflow slides Data Analytics
Stack Overflow slides Data Analytics Stack Overflow slides Data Analytics
Stack Overflow slides Data Analytics Rahul Thankachan
 

Viewers also liked (20)

Soluciones tecnológicas para REA
Soluciones tecnológicas para REASoluciones tecnológicas para REA
Soluciones tecnológicas para REA
 
Implementación Repositorio De Objetos De Aprendizajes Basado En
Implementación Repositorio De Objetos De Aprendizajes Basado EnImplementación Repositorio De Objetos De Aprendizajes Basado En
Implementación Repositorio De Objetos De Aprendizajes Basado En
 
Repositorio Institucional para el manejo de Investigaciones de la UNAN-Manag...
 Repositorio Institucional para el manejo de Investigaciones de la UNAN-Manag... Repositorio Institucional para el manejo de Investigaciones de la UNAN-Manag...
Repositorio Institucional para el manejo de Investigaciones de la UNAN-Manag...
 
What is Node.js used for: The 2015 Node.js Overview Report
What is Node.js used for: The 2015 Node.js Overview ReportWhat is Node.js used for: The 2015 Node.js Overview Report
What is Node.js used for: The 2015 Node.js Overview Report
 
groovy & grails - lecture 13
groovy & grails - lecture 13groovy & grails - lecture 13
groovy & grails - lecture 13
 
Responsive Design
Responsive DesignResponsive Design
Responsive Design
 
Stack_Overflow-Network_Graph
Stack_Overflow-Network_GraphStack_Overflow-Network_Graph
Stack_Overflow-Network_Graph
 
Presentacion MoodleMoot 2014 Colombia - Integración Moodle con un Repositorio...
Presentacion MoodleMoot 2014 Colombia - Integración Moodle con un Repositorio...Presentacion MoodleMoot 2014 Colombia - Integración Moodle con un Repositorio...
Presentacion MoodleMoot 2014 Colombia - Integración Moodle con un Repositorio...
 
Stack Overflow - It's all about performance / Marco Cecconi (Stack Overflow)
Stack Overflow - It's all about performance / Marco Cecconi (Stack Overflow)Stack Overflow - It's all about performance / Marco Cecconi (Stack Overflow)
Stack Overflow - It's all about performance / Marco Cecconi (Stack Overflow)
 
Modern HTML & CSS Coding: Speed, Semantics & Structure
Modern HTML & CSS Coding: Speed, Semantics & StructureModern HTML & CSS Coding: Speed, Semantics & Structure
Modern HTML & CSS Coding: Speed, Semantics & Structure
 
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)
 
StrongLoop Overview
StrongLoop OverviewStrongLoop Overview
StrongLoop Overview
 
Why Scala for Web 2.0?
Why Scala for Web 2.0?Why Scala for Web 2.0?
Why Scala for Web 2.0?
 
Curso avanzado de capacitación en DSpace
Curso avanzado de capacitación en DSpaceCurso avanzado de capacitación en DSpace
Curso avanzado de capacitación en DSpace
 
Html5 devconf nodejs_devops_shubhra
Html5 devconf nodejs_devops_shubhraHtml5 devconf nodejs_devops_shubhra
Html5 devconf nodejs_devops_shubhra
 
Node.js Frameworks & Design Patterns Webinar
Node.js Frameworks & Design Patterns WebinarNode.js Frameworks & Design Patterns Webinar
Node.js Frameworks & Design Patterns Webinar
 
Webstock 2010 - Stack Overflow: Building Social Software for the Anti-Social
Webstock 2010 - Stack Overflow: Building Social Software for the Anti-SocialWebstock 2010 - Stack Overflow: Building Social Software for the Anti-Social
Webstock 2010 - Stack Overflow: Building Social Software for the Anti-Social
 
Toronto node js_meetup
Toronto node js_meetupToronto node js_meetup
Toronto node js_meetup
 
Introducing the New DSpace User Interface
Introducing the New DSpace User InterfaceIntroducing the New DSpace User Interface
Introducing the New DSpace User Interface
 
Stack Overflow slides Data Analytics
Stack Overflow slides Data Analytics Stack Overflow slides Data Analytics
Stack Overflow slides Data Analytics
 

Similar to Asynchronous Programming Done Right Without Race Conditions

Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSAdam L Barrett
 
Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0Binary Studio
 
Expert JavaScript tricks of the masters
Expert JavaScript  tricks of the mastersExpert JavaScript  tricks of the masters
Expert JavaScript tricks of the mastersAra Pehlivanian
 
Angular promises and http
Angular promises and httpAngular promises and http
Angular promises and httpAlexe Bogdan
 
Promises - Asynchronous Control Flow
Promises - Asynchronous Control FlowPromises - Asynchronous Control Flow
Promises - Asynchronous Control FlowHenrique Barcelos
 
JavaScript Multithread or Single Thread.pptx
JavaScript Multithread or Single Thread.pptxJavaScript Multithread or Single Thread.pptx
JavaScript Multithread or Single Thread.pptxRAHITNATH
 
Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the wayOleg Podsechin
 
TDC2018SP | Trilha Go - Processando analise genetica em background com Go
TDC2018SP | Trilha Go - Processando analise genetica em background com GoTDC2018SP | Trilha Go - Processando analise genetica em background com Go
TDC2018SP | Trilha Go - Processando analise genetica em background com Gotdc-globalcode
 
JavaScript (without DOM)
JavaScript (without DOM)JavaScript (without DOM)
JavaScript (without DOM)Piyush Katariya
 
Asynchronous programming with java script and node.js
Asynchronous programming with java script and node.jsAsynchronous programming with java script and node.js
Asynchronous programming with java script and node.jsTimur Shemsedinov
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous JavascriptGarrett Welson
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testingVisual Engineering
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestPavan Chitumalla
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsFrancois Zaninotto
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Domenic Denicola
 

Similar to Asynchronous Programming Done Right Without Race Conditions (20)

Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
 
Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0Binary Studio Academy: Concurrency in C# 5.0
Binary Studio Academy: Concurrency in C# 5.0
 
Expert JavaScript tricks of the masters
Expert JavaScript  tricks of the mastersExpert JavaScript  tricks of the masters
Expert JavaScript tricks of the masters
 
Angular promises and http
Angular promises and httpAngular promises and http
Angular promises and http
 
JS everywhere 2011
JS everywhere 2011JS everywhere 2011
JS everywhere 2011
 
Promises - Asynchronous Control Flow
Promises - Asynchronous Control FlowPromises - Asynchronous Control Flow
Promises - Asynchronous Control Flow
 
JavaScript Multithread or Single Thread.pptx
JavaScript Multithread or Single Thread.pptxJavaScript Multithread or Single Thread.pptx
JavaScript Multithread or Single Thread.pptx
 
Server side JavaScript: going all the way
Server side JavaScript: going all the wayServer side JavaScript: going all the way
Server side JavaScript: going all the way
 
Node js
Node jsNode js
Node js
 
TDC2018SP | Trilha Go - Processando analise genetica em background com Go
TDC2018SP | Trilha Go - Processando analise genetica em background com GoTDC2018SP | Trilha Go - Processando analise genetica em background com Go
TDC2018SP | Trilha Go - Processando analise genetica em background com Go
 
JavaScript (without DOM)
JavaScript (without DOM)JavaScript (without DOM)
JavaScript (without DOM)
 
Asynchronous programming with java script and node.js
Asynchronous programming with java script and node.jsAsynchronous programming with java script and node.js
Asynchronous programming with java script and node.js
 
Intro to Asynchronous Javascript
Intro to Asynchronous JavascriptIntro to Asynchronous Javascript
Intro to Asynchronous Javascript
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testing
 
Kotlin Coroutines and Rx
Kotlin Coroutines and RxKotlin Coroutines and Rx
Kotlin Coroutines and Rx
 
Node js lecture
Node js lectureNode js lecture
Node js lecture
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
Node.js - Best practices
Node.js  - Best practicesNode.js  - Best practices
Node.js - Best practices
 

More from Piotr Pelczar

Pragmatic Monolith-First, easy to decompose, clean architecture
Pragmatic Monolith-First, easy to decompose, clean architecturePragmatic Monolith-First, easy to decompose, clean architecture
Pragmatic Monolith-First, easy to decompose, clean architecturePiotr Pelczar
 
Elasticsearch - SEARCH & ANALYZE DATA IN REAL TIME
Elasticsearch - SEARCH & ANALYZE DATA IN REAL TIMEElasticsearch - SEARCH & ANALYZE DATA IN REAL TIME
Elasticsearch - SEARCH & ANALYZE DATA IN REAL TIMEPiotr Pelczar
 
[BDD] Introduction to Behat (PL)
[BDD] Introduction to Behat (PL)[BDD] Introduction to Behat (PL)
[BDD] Introduction to Behat (PL)Piotr Pelczar
 
How NOT to write in Node.js
How NOT to write in Node.jsHow NOT to write in Node.js
How NOT to write in Node.jsPiotr Pelczar
 
Liquibase - database structure versioning
Liquibase - database structure versioningLiquibase - database structure versioning
Liquibase - database structure versioningPiotr Pelczar
 

More from Piotr Pelczar (7)

Pragmatic Monolith-First, easy to decompose, clean architecture
Pragmatic Monolith-First, easy to decompose, clean architecturePragmatic Monolith-First, easy to decompose, clean architecture
Pragmatic Monolith-First, easy to decompose, clean architecture
 
Elasticsearch - SEARCH & ANALYZE DATA IN REAL TIME
Elasticsearch - SEARCH & ANALYZE DATA IN REAL TIMEElasticsearch - SEARCH & ANALYZE DATA IN REAL TIME
Elasticsearch - SEARCH & ANALYZE DATA IN REAL TIME
 
[BDD] Introduction to Behat (PL)
[BDD] Introduction to Behat (PL)[BDD] Introduction to Behat (PL)
[BDD] Introduction to Behat (PL)
 
How NOT to write in Node.js
How NOT to write in Node.jsHow NOT to write in Node.js
How NOT to write in Node.js
 
Liquibase - database structure versioning
Liquibase - database structure versioningLiquibase - database structure versioning
Liquibase - database structure versioning
 
CQRS
CQRSCQRS
CQRS
 
Scalable Web Apps
Scalable Web AppsScalable Web Apps
Scalable Web Apps
 

Recently uploaded

DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 

Recently uploaded (20)

DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 

Asynchronous Programming Done Right Without Race Conditions

  • 1. Asynchronous programming done right. Without race conditions ..ions ..io on ..ns ditions. by Piotr Pelczar (Athlan)
  • 2.
  • 3. About me Piotr Pelczar Freelancer for 8yrs PHP, Node.js, Java/Groovy Zend Certified Engineer IPIJ, Startups
  • 4. Stay in touch athlan.pl me@athlan.pl facebook.com/piotr.pelczar github.com/athlan slideshare.net/piotrpelczar linkedin.com/in/ppelczar
  • 5. Asynchronous programming Asynchronous actions are actions executed in a non-blocking scheme, allowing the main program flow to continue processing.
  • 6. How software lives in hardware? Operating systems are process based Each process has assigned processor, registers, memory
  • 7. How software lives in hardware? Process paralelism using threads (thread pools) Switching processor over processes/threads causes context switching
  • 8. 1. context switching = wasting time
  • 9. Sync programming In trivial, sequential approach Each operation is executed sequentially: O(t) > O(t+1) if O(t) stucks, O(t+1) waits...
  • 11. This is cool, software flow is predictible But not in high throughput I/O I/O costs because of waiting time...
  • 12. High throughput I/O High throughput I/O doesn't mean: Memory operations Fast single-thread computing
  • 13. High throughput I/O High throughput I/O means: HTTP requests Database connections Queue system dispatching HDD operations
  • 14. 2. Avoid I/O blocking
  • 15. 2. Avoid I/O blocking
  • 16. Single-threaded, event loop model Imagine a man, who has a task: Walk around When bucket is full of water, just pour another bucket Go to next bucket
  • 17. There is no sequences In async programming, results appears in no sequences operation1(); // will output "operation1 finished." operation2(); // will output "operation2 finished." operation3(); // will output "operation3 finished."
  • 18. There is no sequences operation1() would be var amqp = require("amqp") var eventbus = amqp.createConnection(); console.log("AMQP connecting..."); eventbus.on("ready", function() { console.log("AMQP connected..."); callback(); return; });
  • 19. There is no sequences operation2() would be var redis = require("redis") var conn = redis.createClient(port, host, options); console.log("Redis connecting..."); conn.auth(pass, function(err) { if(err) console.log("Redis failed..."); else console.log("Redis connected..."); callback(); return; });
  • 20. There is no sequences operation3() would be var mongojs = require("mongojs"); console.log("Mongo connecting..."); var conn = mongojs.connect(connectionString); // blocking operation console.log("Mongo connected..."); callback(); return;
  • 21. There is no sequences Expectations? AMQP connecting... // operation1() AMQP connected... // operation1() Redis connecting... // operation2() Redis failed... // operation2() Mongo connecting... // operation3(), blocking Mongo connected... // operation3()
  • 22. There is no sequences Expectations?
  • 23. There is no sequences The result: AMQP connecting... // operation1() Redis connecting... // operation2() Mongo connecting... // operation3(), blocking Mongo connected... // operation3() Redis failed... // operation2() AMQP connected... // operation1()
  • 24. There is no sequences
  • 25. So... what functions returns? You can perform future tasks in function, so what will be returned? value123 will be returned, function my_function() { operation1(); operation2(); operation3(); return "value123"; } just after blocking code, without waiting for non-blocking.
  • 26. Assume: Functions does NOT returns values The function block is executed immedietally from top to bottom. You cannot rely to return value, because it is useless.
  • 27. Callbacks Callback is the reference to function. var callbackFunction = function(result) { console.log("Result: %s", result) } When operation is done, the callback function is executed. callbackFunction("test1") // "Result: test1" will be printed out
  • 28. Callbacks If callbackFunction is a variable (value = reference), so can be passed it via function argument. var callbackFunction = function() { ... } someOtherFunction(callbackFunction); function someOtherFunction(callback) { callback(); // execute function from argument }
  • 29. Callbacks Functions can be defined as anonymous (closures) function someOtherFunction(callback) { var arg1 = "test"; callback(arg1); // execute function from argument } someOtherFunction(function(arg1) { console.log('done... %s', arg1); })
  • 30. Callbacks can be nested Nesting callbacks makes code unreadeable: var amqp = require('amqp'); var connection = amqp.createConnection(); connection.on('ready', function() { connection.exchange("ex1", function(exchange) { connection.queue('queue1', function(q) { q.bind(exchange, 'r1'); q.subscribe(function(json, headers, info, m) { console.log("msg: " + JSON.stringify(json)); }); }); }); });
  • 31. Callbacks can be nested Nesting callbacks makes code unreadeable: var amqp = require('amqp'); var connection = amqp.createConnection(); connection.on('ready', function() { connection.exchange("ex1", function(exchange) { connection.queue('queue1', function(q) { q.bind(exchange, 'r1'); q.subscribe(function(json, headers, info, m) { console.log("msg: " + JSON.stringify(json)); table.update(select, data, function() { table.find(select, function(err, rows) { // inserted rows... } }); }); }); }); });
  • 32. Asynchronous control flows Promise design pattern Libraries that manages callbacks references
  • 33. Promise design pattern 1. Client fires function that will return result in the future in the future, so it is a promise 2. Function returns promise object immedietaly before non-blocking operations 3. Client registers callbacks 4. Callbacks will be fired in the future, when task is done var resultPromise = loader.loadData(sourceFile) resultPromise(function success(data) { // this function will be called while operation will succeed }, function error(err) { // on fail })
  • 34. Promise design pattern 1. Create deferred object 2. Return def.promise 3. Call resolve() or reject() var loadData = function(sourceFile) { var def = deferred() , proc = process.spawn('java', ['-jar', 'loadData.jar', sourceFile]) var commandProcessBuff = null , commandProcessBuffError = null; proc.stdout.on('data', function (data) { commandProcessBuff += data }) proc.stderr.on('data', function (data) { commandProcessBuffError += data }) proc.on('close', function (code) { if(null !== commandProcessBuffError) def.reject(commandProcessBuffError) else def.resolve(commandProcessBuff) }) return def.promise }
  • 36. Async Node.js library Provides control flows like: Sequences (series) Waterfalls (sequences with parameters passing) Parallel (with limit) Some/every conditions While/until Queue
  • 38. Async Node.js library Series async.series([ function(callback) { // operation1 }, function(callback) { // operation2 }, function(callback) { // operation3 } ], function() { console.log('all operations done') })
  • 39. Async Node.js library Parallel async.parallel([ function(callback) { // operation1 }, function(callback) { // operation2 }, function(callback) { // operation3 } ], function() { console.log('all operations done') })
  • 40. Async Node.js library Parallel limit
  • 41. Async Node.js library Parallel limit var tasks = [ function(callback) { // operation1 }, function(callback) { // operation2 }, // ... ] async.parallelLimit(tasks, 2, function() { console.log('all operations done') })
  • 42. Async Node.js library Waterfall async.waterfall([ function(callback) { // operation1 callback(null, arg1, arg2) }, function(arg1, arg2, callback) { // operation2 callback(null, foo, bar) }, function(foo, bar, callback) { // operation3 } ], function() { console.log('all operations done') })
  • 43. Async Node.js library Whilst async.doWhilst( function(done) { // operation1 done(null, arg1, arg2) }, function() { return pages < limit } ], function() { console.log('done') })
  • 44. Asynchronous programming traps Dealing with callbacks may be tricky. Keep your code clean.
  • 45. Unnamed callbacks Keep your code clean, don't name callback function callback function doSomething(callback) { return callback; }
  • 46. Unnamed callbacks function doSomething(callback) { doAnotherThing(function(callback2) { doYetAnotherThing(function(callback3) { return callback(); }) }) }
  • 47. Unnamed callbacks Instead of this, name your callbacks function doSomething(done) { doAnotherThing(function(doneFetchingFromApi) { doYetAnotherThing(function(doneWritingToDatabase) { return done(); }) }) }
  • 48. Double callbacks function doSomething(done) { doAnotherThing(function (err) { if (err) done(err); done(null, result); }); } Callback is fired twice!
  • 49. Double callbacks Fix: Always prepend callback execution with return statement. function doSomething(done) { doAnotherThing(function (err) { if (err) return done(err); return done(null, result); }); } Normally, return ends function execution, why do not keep this rule while async.
  • 50. Double callbacks Double callbacks are very hard to debug. The callback wrapper can be written and execute it only once. setTimeout(function() { done('a') }, 200) setTimeout(function() { done('b') }, 500)
  • 51. Double callbacks var CallbackOnce = function(callback) { this.isFired = false this.callback = callback } CallbackOnce.prototype.create = function() { var delegate = this return function() { if(delegate.isFired) return delegate.isFired = true delegate.callback.apply(null, arguments) } }
  • 52. Double callbacks obj1 = new CallbackOnce(done) // decorate callback safeDone = obj1.create() // safeDone() is proxy function that passes arguments setTimeout(function() { safeDone('a') // safe now... }, 200) setTimeout(function() { safeDone('b') // safe now... }, 500)
  • 53. Unexpected callbacks Never fire callback until task is done. function doSomething(done) { doAnotherThing(function () { if (condition) { var result = null // prepare result... return done(result); } return done(null); }); } The ending return will be fired even if condition pass.
  • 54. Unexpected callbacks Never fire callback until task is done. function doSomething(done) { doAnotherThing(function () { if (condition) { var result = null // prepare result... return done(result); } else { return done(null); } }); }
  • 55. Unexpected callbacks Never use callback in try clause! function (callback) { another_function(function (err, some_data) { if (err) return callback(err); try { callback(null, JSON.parse(some_data)); // error here } catch(err) { callback(new Error(some_data + ' is not a valid JSON')); } }); } If callback throws an exception, then it is executed exactly twice!
  • 56. Unexpected callbacks Never use callback in try clause! function (callback) { another_function(function (err, some_data) { if (err) return callback(err); try { var parsed = JSON.parse(some_data) } catch(err) { return callback(new Error(some_data + ' is not a valid JSON')); } callback(null, parsed); }); }
  • 57. Unexpected callbacks Never use callback in try clause!
  • 58. Take care of events Read docs carefully. Really. function doSomething(done) { var proc = process.spawn('java', ['-jar', 'loadData.jar', sourceFile]) var procBuff = ''; proc.stdout.on('data', function (data) { procBuff += data; }); // WAT?! proc.stderr.on('data', function (data) { done(new Error("An error occured: " + data)) }); proc.on('close', function (code) { done(null, procBuff); } }
  • 59. Take care of events Read docs carefully. Really. function doSomething(done) { var proc = process.spawn('java', ['-jar', 'loadData.jar', sourceFile]) var procBuff = ''; var procBuffError = ''; proc.stdout.on('data', function (data) { procBuff += data; }); proc.stderr.on('data', function (data) { proc += data; }); proc.on('close', function (code) { if(code !== 0) { return done(new Error("An error occured: " + procBuffError)); } else { return done(null, procBuff) } } }
  • 60. Unreadable and logs Keep in mind, that asynchronous logs will interweave There are not sequenced Or there will be same log strings
  • 61. Unexpected callbacks Asynchronous logs will interweave
  • 62. Unreadable and logs Logs without use context are useless... function getResults(keyword, done) { http.request(url, function(response) { console.log('Fetching from API') response.on('error', function(err) { console.log('API error') }) }); }
  • 63. Unreadable and logs function getResults(keyword, done) { var logContext = { keyword: keyword } http.request(url, function(response) { console.log(logContext, 'Fetching from API') response.on('error', function(err) { console.log(logContext, 'API error') }) }); }
  • 64. Unreadable and logs Centralize your logs - use logstash And make them searcheable - Elasticsearch + Kibana
  • 65. Too many opened background-tasks While running parallel in order to satisfy first-better algorithm, others should be aborted
  • 66. Too many opened background-tasks Provide cancellation API: var events = require('events') function getResults(keyword) { var def = deferred() var eventbus = new events.EventEmitter() var req = http.request(url, function(response) { var err = null , content = null res.on('data', function(chunk) { content += chunk; }); response.on('close', function() { if(err) return def.reject(err) else return def.resolve(content) }) response.on('error', function(err) { err += err }) });
  • 67. Too many opened background-tasks Provide cancellation API: var response = getResults('test') response.result(function success() { // ... }, function error() { // ... }) // if we need response.events.emit('abort')
  • 68. Everything runs in parallel except your code. When currently code is running, (not waiting for I/O descriptors) whole event loop is blocked.
  • 69. THE END by Piotr Pelczar
  • 70. Q&A by Piotr Pelczar