Skip to content

Instantly share code, notes, and snippets.

@angelworm
Created February 1, 2016 23:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save angelworm/77a60f3c3f42c7bc7587 to your computer and use it in GitHub Desktop.
Save angelworm/77a60f3c3f42c7bc7587 to your computer and use it in GitHub Desktop.
callback hellを避けるけど同期処理のようにもしない奴
// utility ----------------------------------------------------------
function isGenerator(o) {
return (typeof o === "object") && (typeof o.next === "function");
}
function isPromise(o) {
return (typeof o === "object") && (typeof o.then === "function");
}
function isTag(o) {
return (typeof o === "object") && (o.tag === "tag");
}
// wrapper ----------------------------------------------------------
function tag(promise) {
return {tag: "tag", value: promise};
}
function untag(tag) {
return isTag(tag) ? tag.value : null;
}
// main -------------------------------------------------------------
function lazy(g) {
return new Promise(function(resolve, reject) {
window.setTimeout(function() {
C$(g).then(resolve, reject);
}, 1000 + Math.random() * 100);
});
}
function C$sub(g, o, resolve, reject) {
while(true) {
var y = g.next(o);
o = y.value;
if(y.done) {
return resolve(o);
} else if(isGenerator(o)) {
o = tag(lazy(o));
} else if(isPromise(o)) {
o = tag(o);
} else if(isTag(o)) {
var promise = untag(o);
return promise.then(function(v) {
C$sub(g, v, resolve, reject);
}, reject);
} else {
return resolve(o);
}
}
}
function c(g) {
return new Promise(function(resolve, reject) {
C$sub(g, null, resolve, reject);
});
}
// test -------------------------------------------------------------
function *fa(x) {
console.log("fa", x);
return x;
}
function fb(x, delay) {
console.log("fb", x, delay);
return new Promise(function(resolve, reject) {
window.setTimeout(resolve.bind(window, x), delay);
});
}
function *f() {
console.log("f","1");
var a$ = yield fa(1);
var b$ = yield fb(3, 1000 + Math.random() * 100);
console.log("f","2");
var ret = (yield a$) + (yield b$);
console.log("f","3", ret);
return ret;
}
c(f()).then(console.log.bind(console), console.error.bind(console));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment