Re: Deprecating Future's .then()

Alex Russell <[email protected]>
Newsgroups gmane.comp.web.dom.general
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`.
>
>
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.