node --harmony-generators script.js
Slides: pag.forbesl.co.uk
function count(n){
var res = []
for (var x = 0; x < n; x++) {
res.push(x)
}
return res
}
for (var x of count(5)) {
console.log(x)
}
function count(){
var res = []
for (var x = 0; true; x++) {
res.push(x)
}
return res
}
for (var x of count()) {
console.log(x)
}
function* count(){
for (var x = 0; true; x++) {
yield x
}
}
for (var x of count()) {
console.log(x)
}
function* take(list, n){
var i = 0
for (var x of list) {
if (n === i++) {
return
}
yield x
}
}
for (var x of take(count(), 5)) {
console.log(x)
}
function readJSONSync(filename){
return JSON.parse(fs.readFileSync(filename, 'utf8'))
}
function readJSON(filename, callback){
fs.readFile(filename, 'utf8', function (err, res){
if (err) return callback(err)
callback(null, JSON.parse(res))
})
}
function readJSON(filename, callback){
fs.readFile(filename, 'utf8', function (err, res){
if (err) return callback(err)
try {
callback(null, JSON.parse(res))
} catch (ex) {
callback(ex)
}
})
}
JSON.parse
var n = 0
readJSON(filename, function (err, res){
throw new Error('Unerlated error ' + (n++))
})
function readJSON(filename, callback){
fs.readFile(filename, 'utf8', function (err, res){
if (err) return callback(err)
try {
res = JSON.parse(res)
} catch (ex) {
return callback(ex)
}
callback(null, res)
})
}
function readJSONSync(filename){
return JSON.parse(fs.readFileSync(filename, 'utf8'))
}
function readFile(filename, enc){
return new Promise(function (fulfill, reject){
fs.readFile(filename, enc, function (err, res){
if (err) reject(err)
else fullfill(res)
})
})
}
function readJSON(filename){
return new Promise(function (fulfill, reject){
readFile(filename, 'utf8').done(function (res){
try {
fullfill(JSON.parse(res))
} catch (ex) {
reject(ex)
}
}, reject)
})
}
.then
is to .done
as
.map
is to .forEach
function readJSON(filename){
return readFile(filename, 'utf8').then(function (res){
return JSON.parse(res)
})
}
function readJSON(filename){
return readFile(filename, 'utf8').then(JSON.parse)
}
What if yield could be used to "await" a promise?
var readJSONSync = function (filename){
return JSON.parse(fs.readFileSync(filename, 'utf8'))
}
var readJSON = async(function *(filename){
return JSON.parse(yield readFile(filename, 'utf8'))
})
var get = async(function *(){
var left = yield readJSON('left.json')
var right = yield readJSON('right.json')
return {left: left, right: right}
})
var get = async(function *(){
var left = readJSON('left.json')
var right = readJSON('right.json')
return {left: yield left, right: yield right}
})
var tryGet = async(function *(key, defaultValue){
var result
try {
result = yield get(key)
} catch (ex) {
result = defaultValue
}
return result
})
var uploadDocuments = async(function *(documents){
for (var document of documents) {
yield upload(document)
}
})
var uploadDocumentsParallel = async(function *(documents){
var operations = []
for (var document of documents) {
operations.push(upload(document))
}
for (var operation of operations) {
yield operation
}
})
yield foo
is an expression.next(value)
function* demo() {
var res = yield 10
assert(res === 32)
return 42
}
var d = demo()
var resA = d.next()
// => {value: 10, done: false}
var resB = d.next(32)
// => {value: 42, done: true}
// d.next() - THROWS!!!
.throw(error)
var sentinel = new Error('foo')
function* demo() {
try {
yield 10
} catch (ex) {
assert(ex === sentinel)
}
}
var d = demo()
d.next()
// => {value: 10, done: false}
d.throw(sentinel)
function async(makeGenerator){
return function (){
var generator = makeGenerator.apply(this, arguments)
function handle(result){ // { done: [Boolean], value: [Object] }
if (result.done) return result.value
return result.value.then(function (res){
return handle(generator.next(res))
}, function (err){
return handle(generator.throw(err))
})
}
return handle(generator.next())
}
}
function readJSON(filename, _){
return JSON.parse(fs.readFile(filename, 'utf8', _))
}
suspend(function *(resume){
return JSON.parse(yield fs.readFile(filename, 'utf8', resume))
})
function readFile(filename, encoding){
return function (callback){
return fs.readFile(filename, encoding, callback)
}
}
co(function *(){
return JSON.parse(yield readFile(filename, 'utf8'))
})
Promises let us turn
function readJSON(filename, callback){
fs.readFile(filename, 'utf8', function (err, res){
if (err) return callback(err)
try {
res = JSON.parse(res)
} catch (ex) {
return callback(ex)
}
callback(null, res)
})
}
INTO
function readJSON(filename){
return readFile(filename, 'utf8').then(JSON.parse)
}
Generators let us turn
function get(filename){
return readJSON('left.json').then(function (left){
return readJSON('right.json').then(function (right){
return {left: left, right: right}
})
})
}
INTO
var get = async(function *(){
var left = yield readJSON('left.json')
var right = yield readJSON('right.json')
return {left: left, right: right}
})