Asynchronous programming with java script and node.js

49
Asynchronous Programming with JavaScript and Node.js Timur Shemsedinov Software Architect at Metarhia, Lecturer at KPI

Transcript of Asynchronous programming with java script and node.js

Page 1: Asynchronous programming with java script and node.js

Asynchronous Programmingwith JavaScript and Node.js

Timur ShemsedinovSoftware Architect at Metarhia, Lecturer at KPI

Page 2: Asynchronous programming with java script and node.js

Metarhia

Page 3: Asynchronous programming with java script and node.js

Asynchronous programming in JavaScript as of today

● callbacks● async.js● promises● async/await● ?

Page 4: Asynchronous programming with java script and node.js

Asynchronous programming in JavaScript as of today

● callbacks● async.js● promises● async/await● generators/yield● events● functor + chaining + composition

Page 5: Asynchronous programming with java script and node.js

Asynchronous programming in JavaScript as of today

● callbacks > async.js● promises > async/await● events● functor + chaining + composition

Page 6: Asynchronous programming with java script and node.js

Callbacks

(callback) => callback(data)

(...args, callback) => callback(err, data)

Use contracts: callback-last, error-firstYou can implement hell easely

Page 7: Asynchronous programming with java script and node.js

Callbacks

readConfig('myConfig', (e, data) => { query('select * from cities', (e, data) => { httpGet('http://kpi.ua', (e, data) => { readFile('README.md', (e, data) => { }); }); });});

Page 8: Asynchronous programming with java script and node.js

Callbacks

readConfig('myConfig', query.bind(null, 'select * from cities', httpGet.bind(null, 'http://kpi.ua', readFile.bind('README.md', () => { }); }); });});

Page 9: Asynchronous programming with java script and node.js

Callbacks

readConfig('myConfig');

function readConfig(fileName) { ...; query('select * from cities');}

function query(statement) {...; httpGet('http://kpi.ua');

}...

Page 10: Asynchronous programming with java script and node.js

Library async.js or analogues

async.method([... (data, cb) => cb(err, result) ...],(err, result) => {}

);

Use callback-last, error-firstDefine functions separately, descriptive namesHell remains

Page 11: Asynchronous programming with java script and node.js

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');

Page 12: Asynchronous programming with java script and node.js

Promise

new Promise((resolve, reject) => { resolve(data); reject(new Error(...));}) .then(result => {}, reason => {}) .catch(err => {});

Separated control flow for success and failHell remains for complex parallel/sequential code

Page 13: Asynchronous programming with java script and node.js

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 }); });

Page 14: Asynchronous programming with java script and node.js

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 });});

Page 15: Asynchronous programming with java script and node.js

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 }); });

Page 16: Asynchronous programming with java script and node.js

async/await

async function f() { return await new Promise(...);}

f().then(console.log).catch(console.error);

Promises under the hood, Control-flow separatedHell remains, Performance reduced

Page 17: Asynchronous programming with java script and node.js

Functor + Chaining + composition

const c1 = chain() .do(readConfig, 'myConfig') .do(doQuery, 'select * from cities') .do(httpGet, 'http://kpi.ua') .do(readFile, 'README.md');

c1();

Page 18: Asynchronous programming with java script and node.js

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;}

Page 19: Asynchronous programming with java script and node.js

Problems

of callbacks, async.js, Promise, async/await

● Nesting and syntax

● Different contracts

● Not cancellable, no timeouts

● Complexity and Performance

Page 20: Asynchronous programming with java script and node.js

Tricks

Page 21: Asynchronous programming with java script and node.js

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);

Page 22: Asynchronous programming with java script and node.js

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); } };}

Page 23: Asynchronous programming with java script and node.js

Make function cancelable

const fn = (par) => { console.log('Function called, par: ' + par);};

const f = cancelable(fn);

f('first');f.cancel();f('second');

Page 24: Asynchronous programming with java script and node.js

Make function cancelable

const cancelable = (fn) => { const wrapper = (...args) => { if (fn) return fn(...args); }; wrapper.cancel = () => { fn = null; }; return wrapper;};

Page 25: Asynchronous programming with java script and node.js

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);

Page 26: Asynchronous programming with java script and node.js

Promisify and Callbackify

const promise = promisify(asyncFunction);promise.then(...).catch(...);

const callback = callbackify(promise);callback((err, value) => { ... });

Page 27: Asynchronous programming with java script and node.js

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); }); }); });});

Page 28: Asynchronous programming with java script and node.js

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));};

Page 29: Asynchronous programming with java script and node.js

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); });

Page 30: Asynchronous programming with java script and node.js

Sync function to Promise

const toPromise = fn => (...args) => new Promise(resolve => resolve(fn(...args)));

Page 31: Asynchronous programming with java script and node.js

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

Page 32: Asynchronous programming with java script and node.js

Metasync

Page 33: Asynchronous programming with java script and node.js

Metasync

● Function composition for asynchronous I/O

● Specific asynchronous abstractions

● Short and expressive syntax

● We use errback compatible contract

● IH

Page 34: Asynchronous programming with java script and node.js

Function composition

inc = a => ++a;square = a => a * a;lg = x => log(10, x);

f = compose(inc, square, lg);

...but it’s synchronous

Page 35: Asynchronous programming with java script and node.js

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

Page 36: Asynchronous programming with java script and node.js

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)

Page 37: Asynchronous programming with java script and node.js

Flow commutation like in electronics

const fx = metasync.flow( [f1, f2, f3, [[f4, f5, [f6, f7], f8]], f9]);

Page 38: Asynchronous programming with java script and node.js

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);

Page 39: Asynchronous programming with java script and node.js

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);});

Page 40: Asynchronous programming with java script and node.js

Key collectorconst 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);

Page 41: Asynchronous programming with java script and node.js

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);

Page 42: Asynchronous programming with java script and node.js

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);

Page 43: Asynchronous programming with java script and node.js
Page 44: 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

Page 45: Asynchronous programming with java script and node.js

Queueconst cq = metasync.queue(3) .wait(2000) .timeout(5000) .throttle(100, 1000) .process((item, cb) => cb(err, result)) .success((item) => {}) .failure((item) => {}) .done(() => {}) .drain(() => {});

Page 46: Asynchronous programming with java script and node.js

Timur Shemsedinovtshemsedinov@github, [email protected]@facebook, marcusaurelius@habrahabr

Github repo: github.com/metarhia/metasynchttp://how.programming.works

Telegram: t.me/metarhia & t.me/nodeuaMetarhia meetups: meetup.com/NodeUA,

meetup.com/HowProgrammingWorks

Page 47: Asynchronous programming with java script and node.js
Page 48: Asynchronous programming with java script and node.js
Page 49: Asynchronous programming with java script and node.js

Metarhia