Skip to content

Instantly share code, notes, and snippets.

@Raynos Raynos/thePoint.md
Created Oct 14, 2012

Embed
What would you like to do?

In other words, the following asynchronous code:

var d = Domain.create()

d.on("error", function (error) {
    console.error("Error with the twitterverse:", error)
})

d.enter()

getTweetsFor("domenic")
    .reduce(findMostMentioned, [])
    .map(function (mostMentioned) {
        return mostMentioned.map(function (user) { return user.username })
    })
    .toArray(function (mostMentionedNames) {
        console.log("Most mentioned names:", mostMentionedNames)
    })

d.exit()

parallels the synchronous code:

try {
    var mostMentioned = findMostMentioned(getTweetsFor("domenic"))
    var mostMentionedNames = mostMentioned.map(function (user) { return user.username })
    console.log("Most mentioned names:", mostMentionedNames)
} catch (error) {
    console.error("Error with the twitterverse: ", error)
}

Note in particular how errors flowed from any step in the process to our catch handler, without explicit by-hand bubbling code.

@domenic

This comment has been minimized.

Copy link

commented Oct 14, 2012

You are exhibiting promises here exactly. Your getTweetsFor, reduce, and map functions are promise-returning, and toArray is just a weaker then in disguise.

@briancavalier

This comment has been minimized.

Copy link

commented Oct 15, 2012

Just to illustrate that this can be modeled easily using a promise chain, here it is using when.js's map+reduce. Similarly, errors always flow to error handler, without explicit/by-hand propagation.

var when = require('when');

// mostMentioned and mostMentionedNames are promises
var mostMentioned = when.reduce(getTweetsFor('domenic'), findMostMentioned, []);
var mostMentionedNames = when.map(mostMentioned, function(user) { return user.username; });
mostMentionedNames.then(function (mostMentionedNames) {
        console.log("Most mentioned names:", mostMentionedNames);
    }, function (error) {
        console.error("Error with the twitterverse:", error);
    }
);

As domenic's article says, promises are easily composable, like regular return values:

when.map(when.reduce(getTweetsFor('domenic'), findMostMentioned, []),
    function(user) { return user.username; })
.then(function (mostMentionedNames) {
        console.log("Most mentioned names:", mostMentionedNames);
    }, function (error) {
        console.error("Error with the twitterverse:", error);
    }
);

That's really the beauty of promises. They are simple building blocks that restore the familiar rules of function application & composition, and exception propagation, even in the face of asynchrony.

@Raynos

This comment has been minimized.

Copy link
Owner Author

commented Oct 16, 2012

@domenic

You are exhibiting promises here exactly. Your getTweetsFor, reduce, and map functions are promise-returning, and toArray is just a weaker then in disguise.

You have it backwards.

  • promises is an eventual value or exception
  • streams is an eventual list of values or exception

Streams are the more powerful, generic format of promises.

.then is just a weaker .pipe in disguise.

@Raynos

This comment has been minimized.

Copy link
Owner Author

commented Oct 16, 2012

@briancavalier @domenic

That's really the beauty of promises. They are simple building blocks that restore the familiar rules of function application & composition, and exception propagation, even in the face of asynchrony.

https://github.com/Raynos/chain-stream#example

Streams + domains do all of that and much more.

domains allow you to handle error flow however you want very granularly and not just "the then promise rules" way.

Streams allow you to handle eventual data cleanly, especially when dealing with lazy streams.

@domenic

This comment has been minimized.

Copy link

commented Oct 18, 2012

I still maintain that you have a hammer and all you see are nails. (In this analogy, promises are a screwdriver. Both can useful for building things but nailing screws into the wall is ignoring the benefits of having them securely screwed.)

@gaearon

This comment has been minimized.

Copy link

commented Jun 21, 2013

That's pretty much Rx vs TPL in .NET world. I use them both happily.

@sandro-pasquali

This comment has been minimized.

Copy link

commented Feb 17, 2014

Promises don't enable anything new. They might be better for some developers. The pseudo-comp-sci arguments are fatuous. AOP can also be wrapped in very sexy theory about how some "rules of ideal programming" are now being properly followed, as you can do with message passing languages, and many other language types. All mothers think their baby is the cutest.

Frankly, the main concern of modern software (and hardware) is dealing with concurrency (and indeterminacy), and the Promise spec doesn't impress in terms of innovation or sophistication. As mentioned, evented stream processors are much more interesting and flexible -- really, infinitely flexible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.