promises-aplus / constructor-spec

Discussion and drafts of a possible spec for creating and resolving promises
10 stars 4 forks source link

Hot/Cold promises #8

Open ForbesLindesay opened 11 years ago

ForbesLindesay commented 11 years ago

I often find myself wanting to create promises that do nothing until you call then on them. Is it just me, or are other people doing this too? If other people are too then should we consider how we support this in resolvers.

Options:

  1. add an .onStart(fn) method to the resolver object (only viable option for #2)
  2. add options to delay calling fn when you create the promise new Promise(fn, {cold: true})
domenic commented 11 years ago

I'm not really seeing why this is useful. Is it to save two parenthesis? I.e. getPromise().then(...) could be replaced with myPromise.then(...)?

ForbesLindesay commented 11 years ago

Yes and no, it makes sense only in fluent APIs. The onStart event would still only be fired once regardless of how many times you trigger it, so if you had a function getPromise that was to return a new promise each time, you'd still use it as a function.

A good example of this kind of API in use is superagent which is an AJAX library with a fluent API.

superagent
  .post('/api/pet')
  .send({ name: 'Manny', species: 'cat' })
  .end(function(res){

  });

The superagent request object is one of those dreaded promise-like objects that conforms to no standards other than its own, I'd like to change that API so that I can do:

superagent
  .post('/api/pet')
  .send({ name: 'Manny', species: 'cat' })
  .then(function(res){

  })
  .done();

The alternative without hot/cold promises would be:

superagent
  .post('/api/pet')
  .send({ name: 'Manny', species: 'cat' })
  .start()
  .then(function(res){

  })
  .done();

I suspect this won't be something for the core spec tbh, but I wanted to see if anyone else had done something similar.

ForbesLindesay commented 11 years ago

I think without hot/cold promises I'd be tempted to refactor somewhat and go for something like:

superagent
  .path('/api/pet')
  .send({ name: 'Manny', species: 'cat' })
  .post()
  .then(function(res){

  })
  .done();

where .post() starts the request and returns a promise.

kriskowal commented 11 years ago

@forbeslindesay I do foresee the need for lazy promises, objects that are not promises so much as they are query builders that have the promise interface, such that the first promise method called starts the work.

Despite thinking about making such things for more than a year, I’m yet to actually make one, so I’m not qualified to comment on any proposed standard. I suspect it might be too early to gather a quorum to drive a spec.

lsmith commented 11 years ago

Interesting idea. My knee jerk reaction was to qualify these as something other than a promise, but I can see how they are analogous in terms of API for expressiveness, different only in the separation of the timing of calling the executor function (supposing Promise(executor) syntax) as noted in #3.

lfac-pt commented 11 years ago

I have been working a fluent API (using https://github.com/kriskowal/q) for making AJAX requests, that is similar in concept to the one described by @ForbesLindesay and from the start I always had the idea of allowing this kind of chaining without incurring unnecessary requests (inspired by this article http://blog.jcoglan.com/2013/03/30/callbacks-are-imperative-promises-are-functional-nodes-biggest-missed-opportunity/).

Does anyone know of any plugin or experimental implementation of this for Q?

Thanks!

junosuarez commented 11 years ago

@lfac-pt there is https://npmjs.org/package/lazy-promise, which is Promises/A+ compatible.

lfac-pt commented 11 years ago

Nice, thank you :)