- From: Alex Russell <slightlyoff@google.com>
- Date: Wed, 5 Jun 2013 10:50:55 +0100
- To: Sean Hogan <shogun70@westnet.com.au>
- 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>
- Message-ID: <CANr5HFV4zFBbxt0G10cPMHHyYn0nKCYTjs_zDWwCUoUfh7bvPQ@mail.gmail.com>
On Saturday, May 18, 2013, Sean Hogan wrote: > After more consideration I think I have some proposed changes which make > Futures more consistent and flexible without compromising the current > compatibility with JS Promise implementations. > > PRIMARY CHANGE: > > The primary change is the addition of two methods - call them `thenfu` and > `catchfu` for now - which become the preferred methods for registering > callbacks. > > `thenfu` and `catchfu` are similar to `then` and `catch` in that they are > called with "accept" and/or "reject" callbacks and that they return a new > Future. > > But they are also similar to the Future constructor in that the associated > resolver is available to the callback (via `this`) as the intended means of > resolving the future. > Adding the resolver for the generated future was discussed here: https://github.com/slightlyoff/Futures/issues/46 The general consensus was that it can be added later if we like. I don't see any need to expand the core contract for now. > EXAMPLE: > > Using `thenfu` might look like this: > > new Future(function() { > this.accept(2); // NOTE: `resolver` is `this` > }) > .thenfu(function(value) { // immediate "accept" > this.accept(value * value); // NOTE: `resolver` is `this` > }) > .then(function(value) { // same thing as previous `thenfu` > return value * value; > }) > .thenfu(function(value) { // a delayed "accept" doesn't require > another new Future > var r = this; > setTimeout(function() { > r.accept(value * 2); > }); > }) > .thenfu(function(value) { // Using `thenfu` with some JS Promise > var promise = getExternalPromiseDependingOnMyValue(value); > promise.then(this.accept, this.reject); > }) > .thenfu(function(value) { // mapping async callback model to Futures > var r = this; > callAsyncFunction(value, function(err, result) { > if (err) r.reject(err); > else r.accept(result); > } > }) > .done(function(value) { > console.log(value); > }); > > > 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`. > > b. easily mix with non-Promise asynchronous code without creating yet > another a new Future > > 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. > > > SECONDARY CHANGES: > > This addition necessitates and / or enables some secondary changes, most > notably: > > a. the deprecation of `then` and `catch` from Future. > > b. the removal of `resolve` from FutureResolver. > > c. the modification of `new Future(init)` so that `resolver` becomes the > `this` object of `init`. > > d. the requirement for `resolver.accept` and `resolver.reject` to be bound > methods, thus enabling them to work when called as bare functions, for > example: > > jsPromise.then(resolver.accept); > > e. It is also necessary to modify `Future.any|every|some` to not rely on > `then` detection. > More on that in a future post. > > > INTEROPERABILITY: > > The advice to JS libs and devs wanting to **mix DOM Futures and Promises** > is: > > 1. `then` and `catch` are deprecated. > > 2. Future objects may be passed to code expecting Promise-like objects > with a `then` method. > > 3. If you call a future's `then` or `catch` then your callback must return > a Promise-like object - that is, an object with a compatible `then` method. > > 3. If you call a future's `thenfu` or `catchfu` then your callback must > use the provided resolver and can accept or reject by any procedure. > > > ASIDE: > > `then` and `catch` can be simply implemented on top of `thenfu` and > `catchfu`. For example, some rough JS code for `catch` would look like: > > > Future.prototype.catch = function(onreject) { // NOTE: assume onreject > is guaranteed a function > this.catchfu(function(value) { > try { > var result = onreject(value); > if (typeof result === 'object' && typeof result.then === > 'function') { > result.then(this.accept, this.reject); > } > else this.accept(result); > } > catch(err) { > this.reject(err); > } > }); > } > > > The reverse is also trivial, but requires the creation of a new Future and > tying it to the one already created by `catch`. > >
Received on Wednesday, 5 June 2013 09:51:22 UTC