Skip to content

Instantly share code, notes, and snippets.

@robotlolita
Created July 23, 2015 21:46
Show Gist options
  • Save robotlolita/a254adc0c8436c5bf1dd to your computer and use it in GitHub Desktop.
Save robotlolita/a254adc0c8436c5bf1dd to your computer and use it in GitHub Desktop.
function nodeify(f) {
return function(...args, cb) {
if (cb == null) {
return f(...args);
} else {
f(...args).then(
function(val) { cb(null, val) },
function(err) { cb(err) }
)
}
}
}
function doThing(message, cb) {
if (typeof cb != "function") {
throw new Error("doThing requires a callback");
}
console.log(message);
cb();
}
function doThingP(message) {
return new Promise(function(resolve, reject) {
doThing(message, resolve);
})
}
// Suppose you're receiving a callback as parameter. Let's call it cb.
// Someone tried to compute that callback, but forgot a return value,
// and now the value passed around ended up being `undefined`
function compose(f, g) {
function _composeResult(x) {
return f(g(x))
}
}
var cb = compose(doMoreThings, doEvenMoreThings);
// We don't know yet that the problem is `cb` being undefined, we assume
// that our definition of `compose` is correct, and that all types are
// going well through our program.
// ---
// If we call `doThing` directly, and pass `cb`, we'll know something is wrong:
doThing("Hello!", cb) // => Error: doThing requires a callback
// Since we got an error telling us what is wrong, we can use a stepping debugger
// to analyse what `cb` is and why it's wrong.
// ---
// If we call `doThingP` directly, we don't need to worry about callbacks because
// promises handle all of that for us. However, because of Promises/A+ semantics
// this will just create a successful promise containing `undefined`,
// that's not really a great idea, and it doesn't really tell us that we've got
// an error.
// (This would never happen if `.then` required a callback. This error is impossible
// to happen in Data.Task, since you can only pass functions)
doThingP("Hello!").then(cb);
// ---
// If we call `nodeify(doThingP)`, two different things can happen:
// If we pass `cb`, we get a promise back. But our code is CPS based, so it's not
// expecting promises to exist at all. This means our whole program hangs, and we
// have no idea of what's happening, or even where to start looking for the error.
// Ideally we'd want the same error as calling `doThing` directly.
nodeify(doThinP)("Hello!", cb);
// If we don't pass `cb`, we get a promise back, and then we have the same problem as
// calling `doThingP` directly:
nodeify(doThingP)("Hello!").then(cb);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment