-
-
Save robotlolita/a254adc0c8436c5bf1dd to your computer and use it in GitHub Desktop.
This file contains hidden or 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
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