SlideShare a Scribd company logo
Asynchronous Programming
with JavaScript and Node.js
Timur Shemsedinov
Software Architect at Metarhia, Lecturer at KPI
Metarhia
Asynchronous programming in JavaScript as of today
● callbacks
● async.js
● promises
● async/await
● ?
Asynchronous programming in JavaScript as of today
● callbacks
● async.js
● promises
● async/await
● generators/yield
● events
● functor + chaining + composition
Asynchronous programming in JavaScript as of today
● callbacks > async.js
● promises > async/await
● events
● functor + chaining + composition
Callbacks
(callback) => callback(data)
(...args, callback) => callback(err, data)
Use contracts: callback-last, error-first
You can implement hell easely
Callbacks
readConfig('myConfig', (e, data) => {
query('select * from cities', (e, data) => {
httpGet('http://kpi.ua', (e, data) => {
readFile('README.md', (e, data) => {
});
});
});
});
Callbacks
readConfig('myConfig',
query.bind(null, 'select * from cities',
httpGet.bind(null, 'http://kpi.ua',
readFile.bind('README.md', () => {
});
});
});
});
Callbacks
readConfig('myConfig');
function readConfig(fileName) {
...; query('select * from cities');
}
function query(statement) {
...; httpGet('http://kpi.ua');
}
...
Library async.js or analogues
async.method(
[... (data, cb) => cb(err, result) ...],
(err, result) => {}
);
Use callback-last, error-first
Define functions separately, descriptive names
Hell remains
Events
const ee = new EventEmitter();
const f1 = () => ee.emit('step2');
const f2 = () => ee.emit('step3');
const f3 = () => ee.emit('done');
ee.on('step1', f1.bind(null, par));
ee.on('step2', f2.bind(null, par));
ee.on('step3', f3.bind(null, par));
ee.on('done', () => console.log('done'));
ee.emit('step1');
Promise
new Promise((resolve, reject) => {
resolve(data);
reject(new Error(...));
})
.then(result => {}, reason => {})
.catch(err => {});
Separated control flow for success and fail
Hell remains for complex parallel/sequential code
Promise Sequential
Promise.resolve()
.then(readConfig.bind(null, 'myConfig'))
.then(query.bind(null, 'select * from cities'))
.then(httpGet.bind(null, 'http://kpi.ua'))
.catch((err) => console.log(err.message))
.then(readFile.bind(null, 'README.md'))
.catch((err) => console.log(err.message))
.then((data) => {
console.dir({ data });
});
Promise Parallel
Promise.all([
readConfig('myConfig'),
doQuery('select * from cities'),
httpGet('http://kpi.ua'),
readFile('README.md')
]).then((data) => {
console.log('Done');
console.dir({ data });
});
Promise Mixed: parallel / sequential
Promise.resolve()
.then(readConfig.bind(null, 'myConfig'))
.then(() => Promise.all([
query('select * from cities'),
gttpGet('http://kpi.ua')
]))
.then(readFile.bind(null, 'README.md'))
.then((data) => {
console.log('Done');
console.dir({ data });
});
async/await
async function f() {
return await new Promise(...);
}
f().then(console.log).catch(console.error);
Promises under the hood, Control-flow separated
Hell remains, Performance reduced
Functor + Chaining + composition
const c1 = chain()
.do(readConfig, 'myConfig')
.do(doQuery, 'select * from cities')
.do(httpGet, 'http://kpi.ua')
.do(readFile, 'README.md');
c1();
Functor + chaining + composition
function chain(prev = null) {
const cur = () => {
if (cur.prev) {
cur.prev.next = cur;
cur.prev();
} else {
cur.forward();
}
};
cur.prev = prev;
cur.fn = null;
cur.args = null;
...
...
cur.do = (fn, ...args) => {
cur.fn = fn;
cur.args = args;
return chain(cur);
};
cur.forward = () => {
if (cur.fn) cur.fn(cur.args, () => {
if (cur.next) cur.next.forward();
});
};
return cur;
}
Problems
of callbacks, async.js, Promise, async/await
● Nesting and syntax
● Different contracts
● Not cancellable, no timeouts
● Complexity and Performance
Tricks
Add timeout to any function
const fn = (par) => {
console.log('Function called, par: ' + par);
};
const fn100 = timeout(100, fn);
const fn200 = timeout(200, fn);
setTimeout(() => {
fn100('first'); fn200('second');
}, 150);
Add timeout to any function
function timeout(msec, fn) {
let timer = setTimeout(() => {
if (timer) console.log('Function timedout');
timer = null;
}, msec);
return (...args) => {
if (timer) {
timer = null;
fn(...args);
}
};
}
Make function cancelable
const fn = (par) => {
console.log('Function called, par: ' + par);
};
const f = cancelable(fn);
f('first');
f.cancel();
f('second');
Make function cancelable
const cancelable = (fn) => {
const wrapper = (...args) => {
if (fn) return fn(...args);
};
wrapper.cancel = () => {
fn = null;
};
return wrapper;
};
More wrappers
const f1 = timeout(1000, fn);
const f2 = cancelable(fn);
const f3 = once(fn);
const f4 = limit(10, fn);
const f5 = throttle(10, 1000, fn);
const f6 = debounce(1000, fn);
const f7 = utils(fn)
.limit(10)
.throttle(10, 100)
.timeout(1000);
Promisify and Callbackify
const promise = promisify(asyncFunction);
promise.then(...).catch(...);
const callback = callbackify(promise);
callback((err, value) => { ... });
Sync function to async
const f1 = par => par; const f2 = par => par;
const f3 = par => par; const f4 = par => par;
console.log(f4(f3(f2(f1('value')))));
const af1 = toAsync(f1); const af2 = toAsync(f2);
const af3 = toAsync(f3); const af4 = toAsync(f4);
af1('value', (e, data) => {
af2(data, (e, data) => {
af3(data, (e, data) => {
af4(data, (e, data) => {
console.log(data);
});
});
});
});
Sync function to async
const last = arr => arr[arr.length - 1];
const toAsync = fn => (...args) => {
const callback = last(args);
args.pop();
callback(null, fn(...args));
};
Sync function to Promise
const f1 = par => par; const f2 = par => par;
const f3 = par => par; const f4 = par => par;
console.log(f4(f3(f2(f1('value')))));
const pf1 = toPromise(f1); const pf2 = toPromise(f2);
const pf3 = toPromise(f3); const pf4 = toPromise(f4);
Promise.resolve()
.then(pf1.bind(null, 'value'))
.then(pf2())
.then(pf3())
.then(pf4())
.then((data) => {
console.log(data);
});
Sync function to Promise
const toPromise = fn => (...args) =>
new Promise(resolve => resolve(fn(...args)));
Convertors
● err-back to Promise
● Promise to err-back
● sync function to Promise
● sync function to err-back
● Events to Promise
● Promise to Events
● Events to err-back
● err-back to Events
Metasync
Metasync
● Function composition for asynchronous I/O
● Specific asynchronous abstractions
● Short and expressive syntax
● We use errback compatible contract
● IH
Function composition
inc = a => ++a;
square = a => a * a;
lg = x => log(10, x);
f = compose(inc, square, lg);
...but it’s synchronous
Function composition
Function composition is a great idea for asynchronous I/O
But there are questions:
● What about contracts?
○ for calls and callbacks, arguments and errors
○ timeouts, queueing, throttling
● How to add asynchronicity?
○ parallel and sequential
Asynchronous function composition
const readCfg = (name, cb) => fs.readFile(name, cb);
const netReq = (data, cb) => http.get(data.url, cb);
const dbReq = (query, cb) => db.select(query, cb);
const f1 = sequential(readCfg, netReq, dbReq);
const f2 = parallel(dbReq1, dbReq2, dbReq3);
// f1 & f2 contracts (...args, cb) => cb(err, data)
Flow commutation like in electronics
const fx = metasync.flow(
[f1, f2, f3, [[f4, f5, [f6, f7], f8]], f9]
);
Data collector
const dc1 = new metasync.DataCollector(4);
const dc2 = new metasync.DataCollector(4, 5000);
dc1.on('error', (err, key) => {});
dc2.on('timeout', (err, data) => {});
dc2.on('done', (errs, data) => {});
dc1.collect(data);
Key collector
const keyCollector = new KeyCollector(
['k1', 'k2'], (data) => console.dir(data)
);
keyCollector.collect('k1', {});
fs.readFile('HISTORY.md', (err, data) => {
keyCollector.collect('history', data);
});
Key collector
const kc = new metasync.KeyCollector(
['user', 'config', 'readme', 'timer'], (data) => console.dir(data)
);
kc.collect('user', { name: 'Marcus Aurelius' });
fs.readFile('HISTORY.md', (err,data) => kc.collect('history', data));
fs.readFile('README.md', (err,data) => kc.collect('readme', data));
setTimeout(
() => keyCollector.collect('timer', { date: new Date() }),
ASYNC_TIMEOUT
);
Collector
const dc1 = metasync
.collect(3)
.timeout(5000)
.done((err, data) => {});
dc1(item);
const dc2 = metasync
.collect(['key1', 'key2', 'key3'])
.timeout(5000)
.done((err, data) => {});
dc2(key, value);
Collector features
const dc = metasync
.collect(count)
.distinct()
.done((err, data) => {});
dc(key, error, value);
dc.pick(key, value);
dc.fail(key, error);
fs.readFile(filename, dc.bind(null, key));
dc.take(key, fs.readFile, filename);
Asynchronous programming with java script and node.js
Throttle
const t1 = metasync.throttle(5000, f);
t1();
t1();
t1(); // single call
setTimeout(t1, 7000); // another call
setTimeout(t1, 7100);
// will be fired at about 7000+5000
Queue
const cq = metasync.queue(3)
.wait(2000)
.timeout(5000)
.throttle(100, 1000)
.process((item, cb) => cb(err, result))
.success((item) => {})
.failure((item) => {})
.done(() => {})
.drain(() => {});
Timur Shemsedinov
tshemsedinov@github, timur.shemsedinov@gmail.com
tshemsedinov@facebook, marcusaurelius@habrahabr
Github repo: github.com/metarhia/metasync
http://how.programming.works
Telegram: t.me/metarhia & t.me/nodeua
Metarhia meetups: meetup.com/NodeUA,
meetup.com/HowProgrammingWorks
Asynchronous programming with java script and node.js
Asynchronous programming with java script and node.js
Metarhia

More Related Content

PDF
Asynchronous programming and mutlithreading
PDF
How are Race Conditions in single threaded JavaScript possible?
PDF
Node.js in 2020 - part 3
PDF
Patterns and antipatterns
PDF
Node.js middleware: Never again!
PDF
Metarhia KievJS 22-Feb-2018
PDF
Race-conditions-web-locks-and-shared-memory
PDF
Node.js in 2020 - part 1
Asynchronous programming and mutlithreading
How are Race Conditions in single threaded JavaScript possible?
Node.js in 2020 - part 3
Patterns and antipatterns
Node.js middleware: Never again!
Metarhia KievJS 22-Feb-2018
Race-conditions-web-locks-and-shared-memory
Node.js in 2020 - part 1

What's hot (20)

PDF
Node.js in 2020
PDF
Node.js in 2020 - part 2
PDF
Новое в JavaScript: ES.Next, ECMAScript 2020, ES11, ES10, ES9, ES8, ES7, ES6,...
PDF
Web Locks API
PDF
Private cloud without vendor lock // Serverless
PDF
JavaScript в браузере: Web API (часть 1)
PDF
Programming Languages: comparison, history, future
PDF
Serverless Clouds (FaaS) and request context isolation in Node.js
PDF
Введение в SQL
PDF
Prototype programming in JavaScript
PDF
How to keep control and safety in the clouds
PDF
JS Fest 2019 Node.js Antipatterns
PDF
Bytes in the Machine: Inside the CPython interpreter
PDF
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
PDF
"A 1,500 line (!!) switch statement powers your Python!" - Allison Kaptur, !!...
PDF
Python opcodes
PDF
Allison Kaptur: Bytes in the Machine: Inside the CPython interpreter, PyGotha...
PDF
JavaScript - Agora nervoso
PDF
Diving into byte code optimization in python
PPTX
TCO in Python via bytecode manipulation.
Node.js in 2020
Node.js in 2020 - part 2
Новое в JavaScript: ES.Next, ECMAScript 2020, ES11, ES10, ES9, ES8, ES7, ES6,...
Web Locks API
Private cloud without vendor lock // Serverless
JavaScript в браузере: Web API (часть 1)
Programming Languages: comparison, history, future
Serverless Clouds (FaaS) and request context isolation in Node.js
Введение в SQL
Prototype programming in JavaScript
How to keep control and safety in the clouds
JS Fest 2019 Node.js Antipatterns
Bytes in the Machine: Inside the CPython interpreter
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
"A 1,500 line (!!) switch statement powers your Python!" - Allison Kaptur, !!...
Python opcodes
Allison Kaptur: Bytes in the Machine: Inside the CPython interpreter, PyGotha...
JavaScript - Agora nervoso
Diving into byte code optimization in python
TCO in Python via bytecode manipulation.
Ad

Similar to Asynchronous programming with java script and node.js (20)

PDF
Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"
PDF
Asynchronous programming done right - Node.js
PPTX
Avoiding Callback Hell with Async.js
PDF
Node js
PDF
Think Async: Asynchronous Patterns in NodeJS
PDF
Event Driven Javascript
PDF
The evolution of java script asynchronous calls
PPTX
Async discussion 9_29_15
PDF
Douglas Crockford: Serversideness
PDF
Promise: async programming hero
PDF
Intro to Asynchronous Javascript
PDF
Kamil witecki asynchronous, yet readable, code
PDF
How to stop debugging asynchronous code and start living, Andrey Salomatin, B...
PPTX
Call stack, event loop and async programming
PPTX
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
PDF
From Node.js to Design Patterns - BuildPiper
ODP
Node js
PPT
You promise?
PDF
The evolution of asynchronous javascript
PDF
Async History - javascript
Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"
Asynchronous programming done right - Node.js
Avoiding Callback Hell with Async.js
Node js
Think Async: Asynchronous Patterns in NodeJS
Event Driven Javascript
The evolution of java script asynchronous calls
Async discussion 9_29_15
Douglas Crockford: Serversideness
Promise: async programming hero
Intro to Asynchronous Javascript
Kamil witecki asynchronous, yet readable, code
How to stop debugging asynchronous code and start living, Andrey Salomatin, B...
Call stack, event loop and async programming
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
From Node.js to Design Patterns - BuildPiper
Node js
You promise?
The evolution of asynchronous javascript
Async History - javascript
Ad

More from Timur Shemsedinov (15)

PDF
How to use Chat GPT in JavaScript optimizations for Node.js
PDF
IT Revolution in 2023-2024: AI, GPT, business transformation, future professi...
PDF
Multithreading in Node.js and JavaScript
PDF
Node.js threads for I/O-bound tasks
PDF
Node.js Меньше сложности, больше надежности Holy.js 2021
PDF
Rethinking low-code
PDF
Hat full of developers
PDF
FwDays 2021: Metarhia Technology Stack for Node.js
PDF
Node.js for enterprise - JS Conference
PDF
Node.js for enterprise 2021 - JavaScript Fwdays 3
PDF
Node.js in 2021
PDF
Information system structure and architecture
PDF
Базы данных в 2020
PDF
Почему хорошее ИТ-образование невостребовано рыночком
PDF
Node.js security
How to use Chat GPT in JavaScript optimizations for Node.js
IT Revolution in 2023-2024: AI, GPT, business transformation, future professi...
Multithreading in Node.js and JavaScript
Node.js threads for I/O-bound tasks
Node.js Меньше сложности, больше надежности Holy.js 2021
Rethinking low-code
Hat full of developers
FwDays 2021: Metarhia Technology Stack for Node.js
Node.js for enterprise - JS Conference
Node.js for enterprise 2021 - JavaScript Fwdays 3
Node.js in 2021
Information system structure and architecture
Базы данных в 2020
Почему хорошее ИТ-образование невостребовано рыночком
Node.js security

Recently uploaded (20)

PDF
Digital Strategies for Manufacturing Companies
PDF
Softaken Excel to vCard Converter Software.pdf
PPTX
Transform Your Business with a Software ERP System
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
AI in Product Development-omnex systems
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
PTS Company Brochure 2025 (1).pdf.......
PDF
medical staffing services at VALiNTRY
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
Understanding Forklifts - TECH EHS Solution
PDF
top salesforce developer skills in 2025.pdf
Digital Strategies for Manufacturing Companies
Softaken Excel to vCard Converter Software.pdf
Transform Your Business with a Software ERP System
Odoo POS Development Services by CandidRoot Solutions
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
AI in Product Development-omnex systems
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
VVF-Customer-Presentation2025-Ver1.9.pptx
PTS Company Brochure 2025 (1).pdf.......
medical staffing services at VALiNTRY
Navsoft: AI-Powered Business Solutions & Custom Software Development
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Upgrade and Innovation Strategies for SAP ERP Customers
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
How to Choose the Right IT Partner for Your Business in Malaysia
CHAPTER 2 - PM Management and IT Context
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Understanding Forklifts - TECH EHS Solution
top salesforce developer skills in 2025.pdf

Asynchronous programming with java script and node.js

  • 1. Asynchronous Programming with JavaScript and Node.js Timur Shemsedinov Software Architect at Metarhia, Lecturer at KPI
  • 3. Asynchronous programming in JavaScript as of today ● callbacks ● async.js ● promises ● async/await ● ?
  • 4. Asynchronous programming in JavaScript as of today ● callbacks ● async.js ● promises ● async/await ● generators/yield ● events ● functor + chaining + composition
  • 5. Asynchronous programming in JavaScript as of today ● callbacks > async.js ● promises > async/await ● events ● functor + chaining + composition
  • 6. Callbacks (callback) => callback(data) (...args, callback) => callback(err, data) Use contracts: callback-last, error-first You can implement hell easely
  • 7. Callbacks readConfig('myConfig', (e, data) => { query('select * from cities', (e, data) => { httpGet('http://kpi.ua', (e, data) => { readFile('README.md', (e, data) => { }); }); }); });
  • 8. Callbacks readConfig('myConfig', query.bind(null, 'select * from cities', httpGet.bind(null, 'http://kpi.ua', readFile.bind('README.md', () => { }); }); }); });
  • 9. Callbacks readConfig('myConfig'); function readConfig(fileName) { ...; query('select * from cities'); } function query(statement) { ...; httpGet('http://kpi.ua'); } ...
  • 10. Library async.js or analogues async.method( [... (data, cb) => cb(err, result) ...], (err, result) => {} ); Use callback-last, error-first Define functions separately, descriptive names Hell remains
  • 11. Events const ee = new EventEmitter(); const f1 = () => ee.emit('step2'); const f2 = () => ee.emit('step3'); const f3 = () => ee.emit('done'); ee.on('step1', f1.bind(null, par)); ee.on('step2', f2.bind(null, par)); ee.on('step3', f3.bind(null, par)); ee.on('done', () => console.log('done')); ee.emit('step1');
  • 12. Promise new Promise((resolve, reject) => { resolve(data); reject(new Error(...)); }) .then(result => {}, reason => {}) .catch(err => {}); Separated control flow for success and fail Hell remains for complex parallel/sequential code
  • 13. Promise Sequential Promise.resolve() .then(readConfig.bind(null, 'myConfig')) .then(query.bind(null, 'select * from cities')) .then(httpGet.bind(null, 'http://kpi.ua')) .catch((err) => console.log(err.message)) .then(readFile.bind(null, 'README.md')) .catch((err) => console.log(err.message)) .then((data) => { console.dir({ data }); });
  • 14. Promise Parallel Promise.all([ readConfig('myConfig'), doQuery('select * from cities'), httpGet('http://kpi.ua'), readFile('README.md') ]).then((data) => { console.log('Done'); console.dir({ data }); });
  • 15. Promise Mixed: parallel / sequential Promise.resolve() .then(readConfig.bind(null, 'myConfig')) .then(() => Promise.all([ query('select * from cities'), gttpGet('http://kpi.ua') ])) .then(readFile.bind(null, 'README.md')) .then((data) => { console.log('Done'); console.dir({ data }); });
  • 16. async/await async function f() { return await new Promise(...); } f().then(console.log).catch(console.error); Promises under the hood, Control-flow separated Hell remains, Performance reduced
  • 17. Functor + Chaining + composition const c1 = chain() .do(readConfig, 'myConfig') .do(doQuery, 'select * from cities') .do(httpGet, 'http://kpi.ua') .do(readFile, 'README.md'); c1();
  • 18. Functor + chaining + composition function chain(prev = null) { const cur = () => { if (cur.prev) { cur.prev.next = cur; cur.prev(); } else { cur.forward(); } }; cur.prev = prev; cur.fn = null; cur.args = null; ... ... cur.do = (fn, ...args) => { cur.fn = fn; cur.args = args; return chain(cur); }; cur.forward = () => { if (cur.fn) cur.fn(cur.args, () => { if (cur.next) cur.next.forward(); }); }; return cur; }
  • 19. Problems of callbacks, async.js, Promise, async/await ● Nesting and syntax ● Different contracts ● Not cancellable, no timeouts ● Complexity and Performance
  • 21. Add timeout to any function const fn = (par) => { console.log('Function called, par: ' + par); }; const fn100 = timeout(100, fn); const fn200 = timeout(200, fn); setTimeout(() => { fn100('first'); fn200('second'); }, 150);
  • 22. Add timeout to any function function timeout(msec, fn) { let timer = setTimeout(() => { if (timer) console.log('Function timedout'); timer = null; }, msec); return (...args) => { if (timer) { timer = null; fn(...args); } }; }
  • 23. Make function cancelable const fn = (par) => { console.log('Function called, par: ' + par); }; const f = cancelable(fn); f('first'); f.cancel(); f('second');
  • 24. Make function cancelable const cancelable = (fn) => { const wrapper = (...args) => { if (fn) return fn(...args); }; wrapper.cancel = () => { fn = null; }; return wrapper; };
  • 25. More wrappers const f1 = timeout(1000, fn); const f2 = cancelable(fn); const f3 = once(fn); const f4 = limit(10, fn); const f5 = throttle(10, 1000, fn); const f6 = debounce(1000, fn); const f7 = utils(fn) .limit(10) .throttle(10, 100) .timeout(1000);
  • 26. Promisify and Callbackify const promise = promisify(asyncFunction); promise.then(...).catch(...); const callback = callbackify(promise); callback((err, value) => { ... });
  • 27. Sync function to async const f1 = par => par; const f2 = par => par; const f3 = par => par; const f4 = par => par; console.log(f4(f3(f2(f1('value'))))); const af1 = toAsync(f1); const af2 = toAsync(f2); const af3 = toAsync(f3); const af4 = toAsync(f4); af1('value', (e, data) => { af2(data, (e, data) => { af3(data, (e, data) => { af4(data, (e, data) => { console.log(data); }); }); }); });
  • 28. Sync function to async const last = arr => arr[arr.length - 1]; const toAsync = fn => (...args) => { const callback = last(args); args.pop(); callback(null, fn(...args)); };
  • 29. Sync function to Promise const f1 = par => par; const f2 = par => par; const f3 = par => par; const f4 = par => par; console.log(f4(f3(f2(f1('value'))))); const pf1 = toPromise(f1); const pf2 = toPromise(f2); const pf3 = toPromise(f3); const pf4 = toPromise(f4); Promise.resolve() .then(pf1.bind(null, 'value')) .then(pf2()) .then(pf3()) .then(pf4()) .then((data) => { console.log(data); });
  • 30. Sync function to Promise const toPromise = fn => (...args) => new Promise(resolve => resolve(fn(...args)));
  • 31. Convertors ● err-back to Promise ● Promise to err-back ● sync function to Promise ● sync function to err-back ● Events to Promise ● Promise to Events ● Events to err-back ● err-back to Events
  • 33. Metasync ● Function composition for asynchronous I/O ● Specific asynchronous abstractions ● Short and expressive syntax ● We use errback compatible contract ● IH
  • 34. Function composition inc = a => ++a; square = a => a * a; lg = x => log(10, x); f = compose(inc, square, lg); ...but it’s synchronous
  • 35. Function composition Function composition is a great idea for asynchronous I/O But there are questions: ● What about contracts? ○ for calls and callbacks, arguments and errors ○ timeouts, queueing, throttling ● How to add asynchronicity? ○ parallel and sequential
  • 36. Asynchronous function composition const readCfg = (name, cb) => fs.readFile(name, cb); const netReq = (data, cb) => http.get(data.url, cb); const dbReq = (query, cb) => db.select(query, cb); const f1 = sequential(readCfg, netReq, dbReq); const f2 = parallel(dbReq1, dbReq2, dbReq3); // f1 & f2 contracts (...args, cb) => cb(err, data)
  • 37. Flow commutation like in electronics const fx = metasync.flow( [f1, f2, f3, [[f4, f5, [f6, f7], f8]], f9] );
  • 38. Data collector const dc1 = new metasync.DataCollector(4); const dc2 = new metasync.DataCollector(4, 5000); dc1.on('error', (err, key) => {}); dc2.on('timeout', (err, data) => {}); dc2.on('done', (errs, data) => {}); dc1.collect(data);
  • 39. Key collector const keyCollector = new KeyCollector( ['k1', 'k2'], (data) => console.dir(data) ); keyCollector.collect('k1', {}); fs.readFile('HISTORY.md', (err, data) => { keyCollector.collect('history', data); });
  • 40. Key collector const kc = new metasync.KeyCollector( ['user', 'config', 'readme', 'timer'], (data) => console.dir(data) ); kc.collect('user', { name: 'Marcus Aurelius' }); fs.readFile('HISTORY.md', (err,data) => kc.collect('history', data)); fs.readFile('README.md', (err,data) => kc.collect('readme', data)); setTimeout( () => keyCollector.collect('timer', { date: new Date() }), ASYNC_TIMEOUT );
  • 41. Collector const dc1 = metasync .collect(3) .timeout(5000) .done((err, data) => {}); dc1(item); const dc2 = metasync .collect(['key1', 'key2', 'key3']) .timeout(5000) .done((err, data) => {}); dc2(key, value);
  • 42. Collector features const dc = metasync .collect(count) .distinct() .done((err, data) => {}); dc(key, error, value); dc.pick(key, value); dc.fail(key, error); fs.readFile(filename, dc.bind(null, key)); dc.take(key, fs.readFile, filename);
  • 44. Throttle const t1 = metasync.throttle(5000, f); t1(); t1(); t1(); // single call setTimeout(t1, 7000); // another call setTimeout(t1, 7100); // will be fired at about 7000+5000
  • 45. Queue const cq = metasync.queue(3) .wait(2000) .timeout(5000) .throttle(100, 1000) .process((item, cb) => cb(err, result)) .success((item) => {}) .failure((item) => {}) .done(() => {}) .drain(() => {});
  • 46. Timur Shemsedinov tshemsedinov@github, timur.shemsedinov@gmail.com tshemsedinov@facebook, marcusaurelius@habrahabr Github repo: github.com/metarhia/metasync http://how.programming.works Telegram: t.me/metarhia & t.me/nodeua Metarhia meetups: meetup.com/NodeUA, meetup.com/HowProgrammingWorks