- 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:17 UTC