I finally looked through the CommonJS proposals this morning.
I plan to write my own proposal and toss it up for discussion in relation to FuturesJS, but here are my ideas as of right now.
Pre-emptive strikes / defense:
- Assignment of literal objects (meaning data, values) is evil.
It leads to scope-creep and promotes disorganization.
If you're pulling data out of your object, you defeat layering.
My rules of thumb: - Parameters (arguments specifying "how") should be passed to functions, but not data.
- Functions should be passed in rather than data being pulled out.
- Literal strings are evil.
In any scope of the program you can access "stringName", but you can only access .methodName() and .propertyName in the correct scope.
Hence strings are inherently global.
They make code more confusing because they take away the context. Such magic strings are the method/property equivalent of magic numbers.
My rules of thumb: - methods and properties should be accessed only in their scope, not via accessors that accept strings.
- If a string doesn't represent literal data or a parameter - from a database, from a user, a helpful user-facing error message - it shouldn't be a string
- Asynchronous / Event-driven programming is better than good, it's great!
Focus is placed on "what should happen if" rather than "when what should happen"
Leads to cleaner, modularized design
Is incompatible with assignment (excepting the case of continuations, but I don't like those)
My rule of thumb:
- Don't abstract away asynchronous programming, embrace it!
- Optional arguments increase complexity. (a mistake a plan to correct in my API when I clean it up)
consider func(callback, errback_opt, progress_opt, params_opt)
What if I want to specify errback and params but not progress? or just progress?
My rules of thumb: - Provide distinct functions for the best-defined use cases.
- Always allow a params_opt as last argument which can be extended with the fluffy stuff.
- Allow `null` (or `false`/`undefined` maybe)??? to require that an argument exists, but not require it to
- Most abbreviations are evil
confusing, unintuitive, just saves a few keystrokes at the expense of readability
My rules of thumb: - Sometimes shortcuts like rm, cp, mv, are nice, so provide both the intuitive remove(), copy(), move(), etc
(or just provide the intuitive ones)
I would like to call to the stand two witnesses
Proposal A: Very straight forward, not very complete
- "progressHandler" callback.
- I like this, I plan to implement it.
- var other_promise = p.get(str_name_of_property_on_result_object)
- I don't really like this because of the whole using strings thing.
- I would implement it as other_promise = p.nameOfProperty(), but I don't see much of a use-case for it
- .then()
- "then" in english implies a sequence of events and I use .then() for sequencing in Futures.
- most libraries examples use .when(), I plan to continue with the defacto standard
- always put callbacks on the queue vs immediate execution if immediately available
- I say provide an option and allow the user to choose.
var p = Promise(callback, { allowSyncback: true });
Proposal B: More full-featured, but somewhat obfuscates the purpose of asynchronous programming
- asap() - solves bullet point 4 above, but there are issues with optional arguments
- asapWhen(), asapFail(), asapProgress()... maybe a bit much
- funcName(object, args)
very python way of passing the object to it's methods rather than having the methods be part of the object
Personally, I don't like this style. I don't feel that JavaScript inherently caters to that style.
- ref(object) - This is similar to Futures.asyncify() with Futures.promise(immediate). I like the idea.
It needs an intuitive name.
I suggest .promisify(). My promisify() handles functions, but I will add the ability to handle promise objects and ready objects.
- when() - this is used by other libraries I've encountered to mean what this proposal calls enqueue.
- get(), post(), del(), put() - neat idea to have shortcuts for CRUD methods, but I don't like the idea of using strings nor micromanaging my data. And what if the object is a literal number? or string? or an array?
- reject() - perhaps a more intuitive name than smash(). I'd be fine with using this.
Immediate thoughts on a proposal C:
- Let the promise object be its own object and handle itself.
- Let promises be duck-type detectable - if it has .when(), it's a promise.
- Specify joins.
- Allow arbitrary extension by using an optional params as the last argument to any function
- params change the internal operation, but not the external outcomes
- i.e. the difference between B's when() and asap() could be handled by a parameter
- specifying or omitting these params will not break compatibility between implementations
I still have some work to do on FuturesJS and defining use cases before I submit my proposal, but my proposal will adhere to my rules of thumbs (with perhaps some exceptions)
The goal of FuturesJS is to *embrace* asynchronous and event-driven programming, not to "deal with it" or hide it.
All of that said, school me. Teach me where I'm being short sighted. I'm always open to understanding a better solution.
AJ ONeal
On Wed, Jul 21, 2010 at 9:20 AM, Nathan Stott
<nrs...@gmail.com> wrote:
Hey it's great to hear that you want to get involved in the CommonJS standardization. Welcome aboard.
On Wed, Jul 21, 2010 at 10:03 AM, CoolAJ86
<cool...@gmail.com> wrote:
I love it - but, hey, I'm building it.
> This came up on the node.js list earlier. We really need a standard promise
> library, but this one seems to deviate from commonjs. Do we have some
> equivalent that we could advertise as an implementation of the promise specs
> from CommonJS?
I'd prefer to conform rather than be shunned and shanked for not being
as cool as the other kids in the sandbox.
I hadn't heard of CommonJS until a few days ago (behind the times, I
know - forgive me).
From the proposals it doesn't apear that there's an actual standard
quite yet.
Let's chat, what can we do to get this converging rather than
deviating?
AJ ONeal