- From: Sean Hogan <shogun70@westnet.com.au>
- Date: Mon, 20 May 2013 11:04:35 +1000
- To: "Tab Atkins Jr." <jackalmage@gmail.com>
- CC: "www-dom@w3.org" <www-dom@w3.org>, "public-script-coord@w3.org" <public-script-coord@w3.org>, Anne van Kesteren <annevk@annevk.nl>
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 <shogun70@westnet.com.au> 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.
Received on Monday, 20 May 2013 01:05:21 UTC