"Plain" values in docs

5 views
Skip to first unread message

Paul Tiseo

unread,
Jun 23, 2013, 12:50:44 AM6/23/13
to cuj...@googlegroups.com
https://github.com/cujojs/when/blob/master/docs/api.md#synchronous-functions

"The when/function module contains functions for calling and adapting "normal" functions (i.e. those that take plain values, return plain values, and throw exceptions on errors)."

Bolded emphasis is mine. What is meant specifically by "plain"? Sorry, but "plain" is a little too vague or informal for me to feel secure in assuming a definition! :)

Charilaos Skiadas

unread,
Jun 23, 2013, 2:29:51 AM6/23/13
to cuj...@googlegroups.com
I think it just means anything but a promise, really. or actually it probably could even be a promise, but it does not have to. Your function returns a normal value, like all javascript functions, and then "when/function" will take that value, and then use it to fulfill its promise. So the functions that had signed up for it via ".then" will be called with that "plain" value as argument.

Simply put, effectively most of the "when" toolkit will automatically turn normal values into promises when it has to.

Here's an even simpler example:

when = require('when');
when(5).then(function(x) {console.log("I got: ", x) });

This will log 5.

And here's an example closer to yours:

fn = require('when/function');
f = function() { return 5; };
fn.call(f).then(function(x) {console.log("I got: ", x) });

This will also log 5. Your function f could be returning whatever it is in the mood for, and fn.call will fulfill its promise with it.

Perhaps "regular" would have been a better term than "plain". Or maybe "plain ol' values" is even better!

Here's rather lengthy promise example from my code that might help you with some of the issues, or might just confuse you more:
https://gist.github.com/skiadas/15890f864aaf15ffbff2

Feel free to just ignore the rest of this really.

Anyone feel free to diss the code, I'm not too happy with it myself. My "db" module is essentially meant to act as a wrapper around mongoDb. The this.connect method is meant to establish a connection with the database, and to keep trying to reconnect if it doesn't succeed. In order for the rest of my code to be able to move forward, I am returning to them a promise object so they can attach db calls that need to happen whenever we manage to establish connection.

In line 8, this.connecting is a place where I'm storing my promise (actually happens in line 33), so if I've already gotten a promise (because say this.connect was called earlier) I just return that. Otherwise, we create a deferred in line 11, and a promise in line 12. The main function is attempt, which attempts to make a connection. It is effectively a promise wrapper around open, which is mongoDb's open function, defined in line 40. A successful connect is routed to the "connected" method, lines 18-23, which records the connection fact, and resolves the promise via the now open this.db object, a reference to the opened mongoDb database. A failed attempt sets a timer for a future attempt. I've set it up so that a few attempts happen back to back, but if it fails to connect after 30 tries it will try a longer interval.
Finally, in line 33 we store this promise, and in line 42 we return it.
Note that this promise will never be rejected really. I could have been rejecting it if I was giving up after a number of attempts, but I decided not to. So the functions passed to "then" might end up waiting forever, for good or for worse.

The rest of the code accesses the database through the function dbPromise, which looks like this:

dbPromise: function() {
return this.connecting || this.connect();
},

Hm looking at it now I feel there is something I could be doing much better in there, so some of this might be a lesson in "things to avoid". Anyway you can see all the ugly painful code and how it is put together here: https://github.com/skiadas/PanthR/blob/master/source/libs/db.js
Can't say it's battle-hardened code yet, as the whole project is very much in flux right now, but might be worth looking at, even if just for a good laugh.

Haris Skiadas

Brian Cavalier

unread,
Jun 23, 2013, 2:59:35 PM6/23/13
to cuj...@googlegroups.com
Hi Paul,

In this case a "plain value" means a "non-thenable".  Where "thenable" is the category of objects or functions with a `then` method.

Care to open a pull request with a rephrasing that you feel clarifies the docs?  It'd certainly be much appreciated.

NOTE: This is an unfortunate categorization, and I'd like to say that a "plain value" is simply a "non-promise".  However, due to the fact that there are implementations, such as jQuery Deferred, that appear to be promises, but are not (they are promise-like, aka "thenable"), we have to have this extra category called "thenable".  when.js will happily consume these things and give you back fully compliant Promises/A+ promises:

var realPromise = when(thenable);

All of when.js's functions (not just when() itself) that accept promises (or arrays of promises) can handle thenables--you don't need to convert them explicitly.

Brian Cavalier

unread,
Jun 23, 2013, 3:03:56 PM6/23/13
to cuj...@googlegroups.com
Hey Haris,

I skimmed your db code quickly, and it looks right to me.  You may want to have a look at when/poll, which implements a similar "poll repeatedly until a condition is satisfied", that it looks like your code is using.  Dunno if it fits the bill for you, but it's worth a look.

Charilaos Skiadas

unread,
Jun 23, 2013, 4:01:00 PM6/23/13
to cuj...@googlegroups.com
On Jun 23, 2013, at 3:03 PM, Brian Cavalier wrote:

> Hey Haris,
>
> I skimmed your db code quickly, and it looks right to me. You may want to have a look at when/poll, which implements a similar "poll repeatedly until a condition is satisfied", that it looks like your code is using. Dunno if it fits the bill for you, but it's worth a look.

Thanks! I remember I did look at when/poll at the time, and did try some things with it, but there was some reason I decided not to use it. I think part of it was that I wanted this flexible interval thing, where I try for the connection a number of times in relatively quick succession, then if all those fail pause for a longer interval. So I think having this "try only 30 times then fail" together with poll, somehow I couldn't quite get it done. I think I should be able to combine when/poll with when/timeout and get more or less the effect I want, but I probably won't revisit that code in a while, there's a whole lot more that needs to be done in other parts of the app.

But I agree with you I'm largely doing what 'when/poll' should be doing for me. I just couldn't quite get it to work the way I wanted, for some reason. Maybe at some point I'll revisit it and try to clean it up.

Haris Skiadas

Brian Cavalier

unread,
Jun 23, 2013, 4:57:46 PM6/23/13
to cuj...@googlegroups.com
Re: flexible interval.  Dunno if this would work for you, but one thought is when/poll's interval param can be a function that returns a promise, so you can, for example, supply an interval function that computes a dynamic interval and then uses when/delay to return a delayed promise.  For example:

var delay = require('when/delay');

function myDynamicInterval() {
    var millis = computeNextIntervalTime();
    return delay(millis);
    // You could also return any non-promise value to signal immediate retry
}

Let me know if that works out for you.
Reply all
Reply to author
Forward
0 new messages