-
-
Save zachallaun/98b685b7e0d90e024d52 to your computer and use it in GitHub Desktop.
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
// Run with `node --harmony coro.js` | |
"use strict"; | |
const Promise = require('bluebird'); | |
// Takes a function*, `g`, that yields promises. | |
// Returns a promise that resolves to `g`'s eventual return value. | |
var coro = function(gStar) { | |
const pending = Promise.pending(); | |
const gArgs = Array.prototype.slice.call(arguments, 1); | |
const gen = gStar.apply(undefined, gArgs); | |
let result; | |
try { result = gen.next(); } | |
catch (e) { | |
pending.reject(e); | |
return pending.promise; | |
} | |
if (result.done) { | |
pending.resolve(result.value); | |
} else { | |
trampoline(gen, result.value, pending); | |
} | |
return pending.promise; | |
}; | |
var trampoline = function(gen, promise, pending) { | |
promise.then(function(input) { | |
let result; | |
try { result = gen.next(input); } | |
catch (e) { | |
pending.reject(e); | |
return; | |
} | |
if (result.done) { | |
pending.resolve(result.value); | |
} else { | |
trampoline(gen, result.value, pending); | |
} | |
}).catch(function(e) { | |
let result; | |
try { result = gen.throw(e); } | |
catch (e) { | |
pending.reject(e); | |
return; | |
} | |
if (result.done) { | |
pending.resolve(result.value); | |
} else { | |
trampoline(gen, result.value, pending); | |
} | |
}); | |
}; | |
var sleep = function*(ms) { | |
return yield Promise.delay(ms); | |
}; | |
var apiCall = function*(endpoint) { | |
yield* sleep(2000); | |
return yield Promise.resolve({ users: ["Foo", "Bar", "Baz"] }); | |
}; | |
var buggyApi = function*(endpoint) { | |
yield Promise.reject(endpoint + " failed!"); | |
}; | |
var bang = function*() { | |
throw "bang!"; | |
}; | |
var outer = function*() { | |
yield* inner(); | |
}; | |
var inner = function*() { | |
yield* sleep(1000); | |
yield* bang(); | |
}; | |
var example = function*(ms) { | |
console.log("Let's sleep for", ms, "milliseconds."); | |
yield* sleep(ms); | |
console.log("And let's now make an expensive api call."); | |
const result = yield* apiCall("/users"); | |
try { yield* bang(); } | |
catch (e) { console.log("bang error", e); } | |
try { yield* outer(); } | |
catch (e) { console.log("outer error", e); } | |
try { yield* buggyApi("/badroute"); } | |
catch (e) { console.log("buggy api", e) } | |
console.log("And let's finish by running some logic."); | |
return result.users.map(user => user.toLowerCase()); | |
}; | |
coro(example, 500) | |
.then(result => console.log("result =", result)) | |
.catch(e => console.log("We got an error!", e)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment