Re: Deprecating Future's .then()

Sean Hogan <[email protected]>
Newsgroups gmane.comp.web.dom.general
Message-ID <[email protected]>
On 20/05/13 8:32 AM, Tab Atkins Jr. wrote:
> I *really* don't like this proposal.  Comments inline, as usual.
>
> On Sat, May 18, 2013 at 3:09 PM, Sean Hogan <[email protected]> wrote:
>> BENEFITS:
>>
>> The main benefits of this addition are:
>>
>> a. consistency in the way futures are initialized and resolved - that is,
>> resolving is always asynchronous via `resolver.accept|reject`.
> This comes at the expense of easier and simpler code to write in the
> common case, when you're receiving an already-built future and are
> just acting on it via .then().  You can no longer just return a value
> like a normal function; you are forced to call `this.accept()`.


You can still do this - I haven't proposed changing the behavior of .then().


> Given that you have to reject the promise based on uncaught errors in
> the callback anyway (or else you lose an important quality of
> promises), `this.reject()` doesn't give you anything
> (`this.reject(val)` is identical to `throw val`, but longer).
>
> You've also removed the ability to do `this.resolve()`, for some
> reason.  This isn't explained at all in your proposal, which makes me
> assume that you don't understand what it's used for.  This means you
> can't force your promise to delegate to another promise, as you can do
> today.


The resolve algorithm is still part of the way .then() handles callbacks 
- I haven't suggested changing that.


> Finally, you're overriding `this` to be the future's resolver, thus
> ruling out any possibility of passing in class methods that want to
> refer to the class instance when processing the future's value.  It's
> unclear what the effect of this would be on hard-bound methods, as
> well.


Yes, I couldn't work out why the callback would want access to the 
resolver's future.
Could you give an example of that usage?

If it is a problem then the resolver could be given a `.future` property 
to reference the context future.


>> b. easily mix with non-Promise asynchronous code without creating yet
>> another a new Future
> Why is this a problem?  It's very simple code:
>
> f.then(function(val) {
>    var resolver, newf = new Future(function(r){ resolver = r; });
>    doAsyncStuff(resolver);
>    return newf;
> }
>
> Here's the code in your proposal:
>
> f.then(function(val) {
>    doAsyncStuff(this);
>    return;
> }


Actually I'm not proposing changing .then().

The example I was thinking of (which I put in my proposal) used the 
Async callback model:

         callAsyncFunction(value, function(err, result) { ... }


> Slightly simpler, but not significantly.  We could even paper over
> this with a convenience method that created a new Future and returned
> a promise/resolver pair, making the gap even smaller.
>
> There is a new Future getting created, but if all you do is return it
> immediately, it'll get GCed away when appropriate.


Yes, the difference is precisely the creation of a new Future. Every time.

I addressed this in my proposal but I'll say it a different way here:

As you say:
     .thenfu() can be implemented with .then() plus the creation of 
*another* new Future

The reverse is also possible and even simpler:
      .then() can be implemented with .thenfu() plus the "resolve" algorithm

So .thenfu is simpler internally and is simpler for mixing with 
non-Promise async code.

.then() is simpler for synchronous code and Promise objects, but...


>
>> c. `then` doesn't need to be the feature-test for Promise objects,
>> and doesn't need to be  a forbidden method of non-Promise objects.
> I don't understand how this is a result of your proposal.


A contrived example:

     var Data = {
         x: 1,
         y: 2,
         then: function() { }
     }

     Future.accept()
     .then(function() {
         return Data;
     })
     .done(function(value) {
         someExternalCodeExpectingData(value);
     });

This chain will stall (silently) because `Data` will be treated as a 
Promise object.
Replace the .then() call with .thenfu and the following won't stall:

     .thenfu(function(value) {
         this.accept(Data);
     })


Personally:
- I want my async code to look like async code;
- I don't like the idea of receiving some quantum "value-or-a-Promise";
- and if my code receives one then I want **my** code to be in charge of 
detecting it.

I doubt I'm the only one who thinks this way.

My proposal:
- suits the async coding pattern,
- adds two methods but **no** complexity to the spec, and
- to my knowledge doesn't compromise the current compatibility with JS 
Promise implementations.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.