creationix / continuable

A continuable style interface to node.js
11 stars 0 forks source link

Either #3

Open Raynos opened 11 years ago

Raynos commented 11 years ago

Continuable's are actually an asynchronous Either implementation

(for reference. Explaining Scala Either, Explaining Either for errors in Haskell)

Based on that understanding I implemented an either function

//  either := (left:(Error) => B, right:(A) => B)
//      => (Continuable<A>) => Continuable<B>
function either(left, right) { return function duplex(source) {
    return function continuable(callback) {
        source(function (err, value) {
            return err ? callback(null, left(err)) :
                callback(null, right(value))
        })
    }
} }

Which then allowed me to remove an if (err) from my code!

// with either
router.addRoute("/posts", function (req, res) {
    var posts = findPosts()
    var subsetOfPosts = map(filterAndSort)(posts)

    var payload = either(function (err) {
        return {
            statusCode: 500,
            body: { message: err.message }
        }
    }, function (posts) { 
        return { statusCode: 200, body: posts } 
    })(subsetOfPosts)

    payload(function (_, value) {
        sendJson(req, res, value)
    })
})

// without either
router.addRoute("/posts", function (req, res) {
    var posts = findPosts()
    var subsetOfPosts = map(filterAndSort)(posts)

    subsetOfPosts(function (err, posts) {
        if (err) {
            return sendJson(req, res, {
                statusCode: 500,
                body: { message: err.message }
            })
        }

        sendJson(req, res, {
            statusCode: 200,
            body: posts
        })
    })
})

In the above example using either(left, right) instead of a manual if doesn't actually make it any simpler but you can imagine it's an improvement for more complex cases