Request for code review: A simple Express (Node.js) web application using Bacon.js

254 views
Skip to first unread message

Erin Swenson-Healey

unread,
Sep 6, 2014, 1:52:58 PM9/6/14
to bac...@googlegroups.com
Hey all,

I've been working on a proof-of-concept in hopes of demonstrating usage of Bacon.js with Express. Code here:


The application transmutes inbound HTTP requests to events in a stream (via Bacon.Bus). A series of transformations are applied to events in the stream, (flat) mapping from request -> mongo query -> record -> response text.

I've never worked with Bacon.js and I'm curious if there were a more-idiomatic way to model this (relatively simple) system. I'd appreciate any feedback - either directly or through the Bacon.js list.

Take care,

Erin

Juha Paananen

unread,
Sep 8, 2014, 4:39:00 PM9/8/14
to Erin Swenson-Healey, bac...@googlegroups.com
You seem to be doing quite fine!

Just had a brief look at your stuff.

You've pretty nicely separated the creation of inputs from processing them and finally generating outputs. Some general comments:

1) input part would benefit from a multi-valued version of Bacon.fromCallback, so it would be easy to avoid using Bus. 
2) you could use onValues instead of onValue to avoid accessing arrays by index
3) i think you could say

    .flatMap(Bacon.fromNodeCallback, db.getBookByTitle)

instead of

    .flatMap(fromQueryToRecord)

4) I'm not sure if point-free style suits Javascripts very well, but that's a matter of opinion

-juha-


--
You received this message because you are subscribed to the Google Groups "Bacon.js" group.
To post to this group, send email to bac...@googlegroups.com.
Visit this group at http://groups.google.com/group/baconjs.

Erin Swenson-Healey

unread,
Sep 8, 2014, 5:38:03 PM9/8/14
to Juha Paananen, bac...@googlegroups.com
Hey Juha,

Thank you for the feedback. I was unaware that flatMap would work in
the manner you described - thanks for that!

Regarding point #1: I'm afraid that I don't quite understand your
suggestion. It appears to be the case (looking at the source code)
that Bacon.fromCallback returns an instance of EventStream through
which (at most) a single event will pass. This is consistent with the
documentation, which states that the "function is supposed to call its
callback just once". It's entirely possible that I am misinterpreting
your advice, though. Could you provide a specific example of how I
could use Bacon.fromCallback to avoid the usage of Bacon.Bus?

Take care,

Erin

Juha Paananen

unread,
Sep 9, 2014, 12:34:27 AM9/9/14
to Erin Swenson-Healey, bac...@googlegroups.com
Oh sorry for being vague wrt point 1.

The suggestion would be to add a new method to bacon.js itself, somthing like feomMultiCalback.

-juha-

Erin Swenson-Healey

unread,
Sep 9, 2014, 5:18:30 PM9/9/14
to Juha Paananen, bac...@googlegroups.com
Hey Juha,

I've implemented fromMultiCallback, viewable here:

https://github.com/laser/bacon.js/blob/features/from_multi_callback/src/Bacon.coffee#L126

I realized just now, though, that this approach suits asynchronous
operations being passed callbacks having an arity 1 only. For example:

The callbacks passed to methods "post" and "get" on an Express route
(http://expressjs.com/4x/api.html#app.route) have an arity of greater
than 1; using Bacon.fromCallback or Bacon.fromMultiCallback would end
up getting the programmer a stream of events giving access to only the
first argument passed to the callback.

I'll go ahead and create a PR for the fromMultiCallback work I've
done, but, as it currently stands - I'm not seeing a good way to use
Bacon with the Express route-handlers! Do you have any thoughts on the
matter?

Once again - I'm looking to do something like:

// original
//
app.get('/foo', function(req, res) {
res.send(req.params.something);
});


// desired
//
requests = Bacon.doSomethingRad(app.get, '/foo')
requests.onValues(function(req, res) {
res.send(req.params.something);
});


// ...but if that were supported, what would we do when...
//
Bacon.doSomethingRad(function(callback) {
setInterval(function() {
callback(['x', 'y', 'z'], [1, 2, 3]);
}, 500);
});


Take care,

Erin
Reply all
Reply to author
Forward
0 new messages