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
Think Async: Asynchronous Patterns in NodeJS
PDF
Asynchronous programming done right - Node.js
PPTX
Avoiding Callback Hell with Async.js
PDF
Job Queue in Golang
PDF
All you need to know about Callbacks, Promises, Generators
PPTX
Столпы функционального программирования для адептов ООП, Николай Мозговой
PDF
用 Go 語言打造多台機器 Scale 架構
PPTX
EcmaScript unchained
PDF
How to practice functional programming in react
KEY
Node.js - Best practices
PDF
Alexey Tsoy Meta Programming in C++ 16.11.17
PPTX
Academy PRO: ES2015
PDF
Rntb20200805
 
PDF
Rxjs vienna
PDF
オープンデータを使ったモバイルアプリ開発(応用編)
PDF
ClojureScript loves React, DomCode May 26 2015
PDF
ES6 - Next Generation Javascript
PDF
Coding in Style
PDF
Refactoring to Macros with Clojure
Timur Shemsedinov "Пишу на колбеках, а что... (Асинхронное программирование)"
Think Async: Asynchronous Patterns in NodeJS
Asynchronous programming done right - Node.js
Avoiding Callback Hell with Async.js
Job Queue in Golang
All you need to know about Callbacks, Promises, Generators
Столпы функционального программирования для адептов ООП, Николай Мозговой
用 Go 語言打造多台機器 Scale 架構
EcmaScript unchained
How to practice functional programming in react
Node.js - Best practices
Alexey Tsoy Meta Programming in C++ 16.11.17
Academy PRO: ES2015
Rntb20200805
 
Rxjs vienna
オープンデータを使ったモバイルアプリ開発(応用編)
ClojureScript loves React, DomCode May 26 2015
ES6 - Next Generation Javascript
Coding in Style
Refactoring to Macros with Clojure
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
How to Make Money in the Metaverse_ Top Strategies for Beginners.pdf
PPTX
Introduction to Windows Operating System
PDF
AI/ML Infra Meetup | Beyond S3's Basics: Architecting for AI-Native Data Access
DOCX
Modern SharePoint Intranet Templates That Boost Employee Engagement in 2025.docx
PDF
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
PDF
Website Design Services for Small Businesses.pdf
PPTX
Oracle Fusion HCM Cloud Demo for Beginners
PPTX
"Secure File Sharing Solutions on AWS".pptx
PDF
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
PPTX
Why Generative AI is the Future of Content, Code & Creativity?
PPTX
Monitoring Stack: Grafana, Loki & Promtail
PPTX
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
DOCX
How to Use SharePoint as an ISO-Compliant Document Management System
PPTX
Trending Python Topics for Data Visualization in 2025
PDF
Top 10 Software Development Trends to Watch in 2025 🚀.pdf
PPTX
Computer Software - Technology and Livelihood Education
PDF
DNT Brochure 2025 – ISV Solutions @ D365
PDF
Topaz Photo AI Crack New Download (Latest 2025)
PDF
iTop VPN Crack Latest Version Full Key 2025
PDF
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
How to Make Money in the Metaverse_ Top Strategies for Beginners.pdf
Introduction to Windows Operating System
AI/ML Infra Meetup | Beyond S3's Basics: Architecting for AI-Native Data Access
Modern SharePoint Intranet Templates That Boost Employee Engagement in 2025.docx
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
Website Design Services for Small Businesses.pdf
Oracle Fusion HCM Cloud Demo for Beginners
"Secure File Sharing Solutions on AWS".pptx
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
Why Generative AI is the Future of Content, Code & Creativity?
Monitoring Stack: Grafana, Loki & Promtail
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
How to Use SharePoint as an ISO-Compliant Document Management System
Trending Python Topics for Data Visualization in 2025
Top 10 Software Development Trends to Watch in 2025 🚀.pdf
Computer Software - Technology and Livelihood Education
DNT Brochure 2025 – ISV Solutions @ D365
Topaz Photo AI Crack New Download (Latest 2025)
iTop VPN Crack Latest Version Full Key 2025
Multiverse AI Review 2025: Access All TOP AI Model-Versions!

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, [email protected] 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