Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

discovery of resolver #5

Open
ForbesLindesay opened this issue Dec 21, 2012 · 7 comments
Open

discovery of resolver #5

ForbesLindesay opened this issue Dec 21, 2012 · 7 comments

Comments

@ForbesLindesay
Copy link
Member

Consider a utility function, timeout:

function timeout(prom, time) {
  let {promise, resolver} = promise();
  resolver.resolve(prom);
  setTimeout(function () {
    resolver.reject(new Error('Operation timed out');
  }, time);
  return promise;
}

The problem with utility functions like these is that I'm not going to get out the same type of promise that I put in. If I passed in something like a Q promise and get back something like a promises-a I loose a lot of functionality.

What if promises came with a property that tells you how to make a new promise, resolver pair:

function timeout(prom, time) {
  let {promise, resolver} = typeof prom.defer === 'function' ?
                            prom.defer() : promise();
  resolver.resolve(prom);
  setTimeout(function () {
    resolver.reject(new Error('Operation timed out');
  }, time);
  return promise;
}

That way if I passed a Q promise in, I'd get a Q promise out.

Do people want this method? What should it be called?

@domenic
Copy link
Member

domenic commented Dec 21, 2012

This is a pretty interesting idea. A bit weird, but not bad.

If we went with a promise-constructor approach, though, it would be more natural, via the constructor property:

function timeout(promise, time) {
  var Promise = promise.constructor;

  return new Promise(function (resolve, reject) {
    promise.then(resolve, reject);
    setTimeout(function () {
      reject(new Error('Operation timed out.'));
    }, time);
  });
}

Writing this down actually gives me the strongest argument for the constructor pattern over the deferred pattern.

@unscriptable
Copy link
Member

This seems like a great way to achieve all of the desired features:

    new Promise(function (resolve, reject) {
      resolve(promise);
      setTimeout(function () {
          reject(new Error('Operation timed out.'));
          // reject function has its own "extension" properties
          // so you could also do this (feel free to bikeshed these names):
          // resolve.createRejectedPromise(new Error('Operation timed out.'));
          // or this:
          // resolve.createCancellablePromise(promise);
          // or this:
          // resolve.createSomeObservablePromise(promise);
      }, 100);
    });

Pros:

  1. fulfillment is obvious and straightforward via function signature. 99% of the time, this is what devs will need
  2. first param can be treated as a resolver with several functions, even proprietary extensions
  3. KISS

Cons:

  1. duplicating the reject function arg as a resolve arg property might feel silly to some

@briancavalier
Copy link
Member

I like this hybrid. It makes the most common operations, resolve & reject, totally obvious and easy to use, while still allowing the resolve function (or reject, I suppose) to be used as the extension point for other to-be-spec'd and proprietary features.

@ForbesLindesay
Copy link
Member Author

@unscriptable @briancavalier both those comments are nothing to do with this issue and everything to do with #7. This issue is about discovering what promise library was used to create an existing promise (so as to be able to create a new promise from the same library). You're comments are about what arguments should be passed to the resolver function.

@juandopazo
Copy link

I worry about the memory footprint of having resolve as both a function and an object with the resolver methods. If we go that way for each promise we'll have to create:

  • All the functions that wrap the the resolver in the promise. If your Promise implementation has getStatus which asks the resolver for its status, then you have an extra function if you want to keep the resolver private
  • Two bound functions: resolve and reject
  • A new function for each method of the resolver that we want to expose to the promise creator

And we don't have __proto__ to avoid creating all those functions. I thought about setting this in the Promise initialization function pointing to the resolver, but it's a little weird.

@ForbesLindesay
Copy link
Member Author

@juandopazo I don't see how your comments relate to this issue, I assume you are still talking about #7.

@juandopazo
Copy link

Yup, my bad.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants