Skip to content

Instantly share code, notes, and snippets.

@zachallaun
Forked from cqfd/coro.js
Last active August 29, 2015 14:22
Show Gist options
  • Save zachallaun/98b685b7e0d90e024d52 to your computer and use it in GitHub Desktop.
Save zachallaun/98b685b7e0d90e024d52 to your computer and use it in GitHub Desktop.
// 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