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

Upload: timur-shemsedinov

Post on 23-Jan-2018

497 views

Category:

Software


4 download

TRANSCRIPT

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