Last active
November 24, 2016 19:39
-
-
Save ifraixedes/62a7155b87e7e7d0c71d to your computer and use it in GitHub Desktop.
Generators & Async function - Source files used for talks (meetups, etc)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Show hidden characters
{ | |
"env": { | |
"development": { | |
"presets":["es2015-node5"], | |
"plugins": ["transform-async-to-generator"] | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
import debug from 'debug'; | |
import {promisedNaturalAdd} from './helpers'; | |
let d = debug('async-funcs'); | |
// NOTE: functions passed to `then` are named to make more clearer for the audience | |
// Basic async function | |
async function basicAsync(num1, num2) { | |
let d = debug('async-funcs:basicAsync'); | |
d('START'); | |
let res = await promisedNaturalAdd(num1, num2); | |
d('END'); | |
return res; | |
} | |
// This is WRONG | |
// This get a promise which resolve or reject when async function ends | |
// It does NOT get the result revolved by the promise or the reject error in synchronous way by try / catch | |
try { | |
let res = basicAsync(10, 5) | |
d('This get a promise object: %s', res); | |
} catch (e) { | |
console.error(e); | |
} | |
// This is RIGTH | |
basicAsync(10, 5).then( | |
function reolved(result) { | |
d('This get the result of the operations made by the async function: %s', result); | |
}, | |
function rejected(err) { | |
console.error(err); | |
} | |
); | |
// This is RIGTH | |
basicAsync(10, -5).then( | |
function reolved(result) { | |
d('This get the result of the operations made by the async function: %s', result); | |
}, | |
function rejected(err) { | |
d('We expected to get this error: "%s"', err); | |
} | |
); | |
// Don't forget to register global events for unhandled rejecte promises | |
basicAsync(10, 5).then( | |
function reolved(result) { | |
// This doesn't parse due the `res` is not defined | |
d(res); // the name of the argument is `result` NOT `res` | |
}, | |
function rejected(err) { | |
console.error(err); | |
} | |
); | |
// without this we have missed the syntax error | |
process.on('unhandledRejection', (err, promise) => { | |
d('Gathered unhandled rejection: %s', err); | |
}); | |
// The body of async function operate synchronously with promise | |
// resolve/reject when `await` statement is used so try/catch just work | |
// inside of them | |
async function basicAsyncTryCatch(num1, num2) { | |
let res; | |
try { | |
d('Basic Async (try-catch): START'); | |
res = await promisedNaturalAdd(num1, num2); | |
} catch (e) { | |
d('Basic Async (try-catch): ERROR: %s', e); | |
} | |
d('Basic Async (try-catch): END'); | |
return res; | |
} | |
basicAsyncTryCatch(10, -5).then( | |
function resolve(res) { | |
d('promise will resolve with undefined: %s', res) | |
}, | |
function reject(e) { | |
d('promise should always resolved so this message should not appear: %s', e); | |
} | |
); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
import debug from 'debug'; | |
import { join, extname } from 'path'; | |
import { readdir, stat } from 'fs'; | |
import { cbToPromise } from './helpers'; | |
let d = debug('listJSFiles'); | |
async function printFilesList(path) { | |
d('listing files'); | |
let filesNames = await cbToPromise(readdir, path); | |
let stats = await Promise.all(filesNames.map(f => cbToPromise(stat, join(path, f)))); | |
stats.forEach((st, idx) => { | |
if (st.isFile() && (extname(filesNames[idx]) === '.js')) { | |
d('file: %s', filesNames[idx]); | |
} | |
}); | |
} | |
printFilesList(__dirname); | |
process.on('unhandledRejection', (err, promise) => { | |
console.error('unhandledRejection: %s', err); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
let d = require('debug')('gen2async'); | |
let promisedNaturalAdd = require('./helpers').promisedNaturalAdd; | |
function asyncify(generator) { | |
function iterate(g, resolvedValue) { | |
let i = g.next(resolvedValue); | |
if (i.done) { | |
return i.value; | |
} | |
return i.value.then(res => { | |
return iterate(g, res); | |
}, err => { | |
g.throw(err); | |
return iterate(g); | |
}); | |
} | |
return function (args) { | |
let g = generator.apply(generator, args); | |
return iterate(g); | |
} | |
} | |
function* gen() { | |
d('START: gen'); | |
let res; | |
try { | |
res = yield promisedNaturalAdd(10, 5); | |
d('First result value (10, 5): %s', res); | |
res = yield promisedNaturalAdd(10, -5); | |
d('Second result value (10, -5): %s', res); | |
} catch (e) { | |
d('Error gathered in catch: %s', e); | |
} | |
d('END: gen'); | |
} | |
let afn = asyncify(gen); | |
afn().then( | |
function () { | |
d('END'); | |
}).catch( | |
function (e) { | |
d('END with error: %s', e); | |
}); | |
process.on('unhandledRejection', (err, promise) => { | |
console.error('unhandledRejection: %s', err); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
let d = require('debug')('generators'); | |
function* simpleGen(initAmount) { | |
yield initAmount; | |
yield initAmount * 10; | |
yield initAmount * 100; | |
} | |
let sg = simpleGen(5); | |
d('Getting value from generator calling next'); | |
while (true) { | |
let i = sg.next(); | |
d(i); | |
if (i.done) { | |
break; | |
} | |
} | |
d('Iterating a generator as an Iterator'); | |
sg = simpleGen(5); | |
for (let i of sg) { | |
d(i); | |
} | |
// LAZY GENERATOR: infinite sequence | |
function* exponential() { | |
let value = 0; | |
while (true) { | |
yield value * value; | |
value++; | |
} | |
} | |
let ex = exponential(); | |
d('Get the 10 first exponential values'); | |
for (let x = 0; x < 10; x++) { | |
let y = ex.next().value; | |
d('x: %s | y: %s', x, y); | |
} | |
d('Get the next 5'); | |
for (let x = 10; x < 15; x++) { | |
let y = ex.next().value; | |
d('x: %s | y: %s', x, y); | |
} | |
// GENERATOR SUBROGATION | |
d('Generator delegates execution to another generator'); | |
function* weirdGrowth() { | |
let x = 0; | |
for (let i = 0; i < 10; i++) { | |
yield* keepConstant(Math.random() * i * 10, i); | |
} | |
} | |
function* keepConstant(times, value) { | |
for (let i = 0; i < times; i++) { | |
yield value; | |
} | |
} | |
let wg = weirdGrowth(); | |
let lastValue = wg.next().value; | |
let counter = 1; | |
for (let i of wg) { | |
if (lastValue !== i) { | |
d('%s value has returned %s times', lastValue, counter); | |
lastValue = i; | |
counter = 1; | |
} else { | |
counter++; | |
} | |
} | |
d('%s value has returned %s times', lastValue, counter); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
let debug = require('debug'); | |
module.exports = { | |
promisedNaturalAdd: promisedNaturalAdd, | |
cbToPromise: cbToPromise | |
}; | |
// NOTE: functions passed to `then` are named with the aim to make it | |
// clearer for some part audience | |
// Remember what a promise is, returning one from a custom function | |
function promisedNaturalAdd(num1, num2) { | |
let d = debug('helpers:promisedNaturalAdd'); | |
d('Delayed Natural Add: START'); | |
let p = new Promise(function (resolve, reject) { | |
// This executes synchronous | |
d('Executing promise callback'); | |
if ((num1 < 0) || (num2 < 0)) { | |
reject(new Error('arguments must be natural numbers')); | |
return; | |
} | |
resolve(num1 + num2); | |
}).then( | |
// This two functions are called asynchronous. | |
// It does NOT matter if the functions passed to | |
// the Promise constructor are called synchronously or asynchronously | |
function resolve(res) { | |
d('This only forward the result'); | |
return res; | |
}, | |
function reject(err) { | |
d('This only forward the error'); | |
throw err; | |
} | |
); | |
d('Delayed Natural Add: END'); | |
return p; | |
} | |
function cbToPromise(fn) { | |
let params = Array.prototype.slice.call(arguments, 1); | |
return new Promise((resolve, reject) => { | |
params.push(function (err) { | |
if (err) { | |
reject(err); | |
return; | |
} | |
switch (arguments.length) { | |
case 1: | |
resolve(); | |
break; | |
case 2: | |
resolve(arguments[1]); | |
break; | |
default: | |
resolve(Array.prototype.slice.call(arguments, 1)); | |
} | |
}); | |
fn.apply(null, params); | |
}); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE Version 2, December 2004 | |
(http://www.wtfpl.net/about/) | |
Copyright (C) 2016 Ivan Fraixedes (https://ivan.fraixed.es) | |
Everyone is permitted to copy and distribute verbatim or modified | |
copies of this license document, and changing it is allowed as long | |
as the name is changed. | |
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE | |
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |
0. You just DO WHAT THE FUCK YOU WANT TO. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "generators-and-async-funcs-talk", | |
"version": "0.0.0", | |
"description": "", | |
"scripts": { | |
"generators": "DEBUG=generators node generators.js", | |
"async": "DEBUG='async-funcs,helpers*' babel-node async-funcs.js", | |
"gen2async": "DEBUG='gen2async,helpers*' node gen-to-async.js", | |
"listFiles": "DEBUG='listJSFiles,helpers*' babel-node example-list-js-files.js" | |
}, | |
"author": "Ivan Fraixedes <[email protected]> (http://ivan.fraixed.es)", | |
"license": "WTFPL", | |
"devDependencies": { | |
"babel-cli": "^6.4.0", | |
"babel-plugin-transform-async-to-generator": "^6.4.0", | |
"babel-preset-es2015-node5": "^1.1.1" | |
}, | |
"dependencies": { | |
"debug": "^2.2.0" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment