Pregunta

Pretty much usual scenario. I want to have some decoupled piece of code, that is triggering event when something is ready. This will happen only once for the whole application run.

On other side, there is another piece of code, where I want something else to happen when two or more events are triggered. I mean like all of them, like dependencies.

Alright, more async things together ... definitely promises right ?

Then I started thinking. Is it really wise to use pub/sub for one time events ? Wouldn't be better to just make accessible promise, that resolves once that event is about to be triggered ? However that would mean I need to kinda interconnect that decoupled code. One thing is having shared EventEmitter, but being dependent on some code to actually create promise ... that sounds rather bad.

So I am thinking about some kind of mix. Having module, where other modules can ask for "event" by it's name and obtaining prepared Promise object. Other module should then trigger that event and effectively fulfilling/rejecting that event this way.

var promisedLand = require('./promisedLand');
promisedLand.waitFor('event'); // returns promise
promisedLand.resolve('event', value);
promisedLand.reject('event', error);

What do you think about this solution ? Any chance there is some solution like this already available ?

¿Fue útil?

Solución 2

Alright, I have made my own solution similar to the one presented in the question.

Welcome to the Promised Land

Otros consejos

Good question. Let me start by one thing: Promises are not event emitters.

Let me reiterate that, since it's a misconception that comes a lot. Promises are not event emitters. With progression, they can be hacked into a form of crippled event emitter but at the end of the day. Promises are not event emitters.

Promises

What are they? Promises are a "box" over a value which you can open at some point using the .then method and then put the result in another box. Nothing more, nothing less.

Like you said, promises are one time. If your event is a one time event - then promises are definitely ok. Essentially, your event is an eventuality and promises model it better most of the time.

Promises as emitters

The problem with using promises as event emitters is composition, progression events in promises simply did not compose very well. Promises chain and compose and events don't. This is why the Q library is dumping progression in favor of estimation in v2. This is why progression was never included in ECMAScript 6.

Event emitters are a perfectly fine abstraction on their own, use event emitters when they're the right tool to model your relation (pub-sub), use promises when they're the right tool to model your relation, use streams when they're the right tool to model your relation. Just don't use one tool for everything as this (from experience) will bring you nothing but a lot of pain.

What I described in my question is really cool though, what about that?

What you're looking for? Oh, that exist. It's quite wonderful actually though it also comes with its own sets of problems.

What you're looking for is called FRP - functional reactive programming. There are a lot of libraries that do that with the best one (in my opinion) being BaconJS.

FRP has the notion of observables you were talking about. Here is an example of a counter from the BaconJS website:

var up   = $('#up').asEventStream('click');
var down = $('#down').asEventStream('click');
 
var counter =
  // map up to 1, down to -1
  up.map(1).merge(down.map(-1))
  // accumulate sum
    .scan(0, function(x,y) { return x + y });
 
// assign observable value to jQuery property text
counter.assign($('#counter'), 'text');

Very similar to promises in chaining, but does not represent a direct continuation but a continuous streaming and a sink.

FRP is a very common and developed paradigm in functional languages like Haskell, and is very applicable in JavaScript. It's not very common yet and it has its own shortcomings, but it definitely thinks like what you had in mind.

So, short recap:

  • Promises are not event emitters. Promises are awesome and majestic and solve a lot of interesting concurrency problems - but they are not a silver bullet for all your decoupled flow control.
  • FRP is this cool thing you came up with but didn't formulate yet. It has a notion of observables and events exactly as you described in your question.

Also, you can pat yourself on the back for thinking about a paradigm without knowing it on your own. You deserve it, honest.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top