Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Add "any" method on $q service #11808

Closed
candreoliveira opened this issue May 5, 2015 · 4 comments
Closed

Add "any" method on $q service #11808

candreoliveira opened this issue May 5, 2015 · 4 comments

Comments

@candreoliveira
Copy link

$q is a service inspired by Kris Kowal's Q.

It's usual in frontend applications make requests to some APIs and based on (at least) an answer continue processing the business logic.

For example: Imagine an e-commerce application. It almost always needs to receive coupons, vouchers and/or freight discounts. A good architecture will separate responsabilities into distinct micro-services. However, the "perfect" ui could be a single input text. So, we'd use a single input to dispatch 3 requests (3 end-points: coupon, voucher and freight discount) and based on any answer apply the user discount. Hence, we need the ability to manage all requests into a single promise.

The Kris Kowal's Q has the method "any" and I think It's very helpful. What do you think about it @IgorMinar ?

@SanderElias
Copy link

@candreoliveira, I think this is a bad idea. There is the .race in the ES standard, it's an better idea to implement that.

I like the functionality, but if there is a documented standart, it's better to comply to that right?
Edit:
Hmm, after an reread of your msg, isn't .all([promise,promise,promise]) taking care of that already?

@jrencz
Copy link

jrencz commented Sep 25, 2015

@candreoliveira I can confirm $q.all fulfils your needs: In the example you've given you definitely want to wait until all services respond: All in all you need to know whether user has 1, 2 or 3 sources of discount and you want to sum up the discount.

@SanderElias I see no cons of adding both .any and .race - they have different semantics: .race will get rejected after the first one of the promises given to it gets rejected. .all will wait for all of them to get rejected.described below

There's #12929 for race

@jrencz
Copy link

jrencz commented Sep 25, 2015

@SanderElias I was wrong about the semantics of .all and rejection: .all gets rejected with a reason the first of rejected promise got rejected with. Still .all, .race and .any have different semantics clearly.

.any with semantics as described by @candreoliveira in his PR seems to be a .race of .race and a promise constructor call (using ES6 syntax for brevity):

// This code is not meant for production!
angular.module('myModule').config(function ($provide) {
  $provide.decorator('$q', function ($delegate) {
    $delegate.race = () => {}; // Let's assume it's implemented according to the Promise spec

    $delegate.any = promises => $delegate.race([
      // covers the case of "resolve when first is resolved"
      $delegate.race(promises),
      // covers the case of "reject when all are rejected"
      $delegate((__resolve, reject) => {
        const reasons = [];
        const bind = (promise, promisesSize) => promise.catch(reason => {
          reasons.push(reason);
          if (reasons.length === promisesSize) {
            reject(reasons);
          }
          return $delegate.reject(reason);
        });

        if (Array.isArray(promises)) {
          const promisesSize = promises.length;
          promises.forEach(promise => {
            bind(promise, promisesSize);
          })
        } else if (typeof promises === 'object' && promises != null) {
          const promisesSize = Object.getOwnPropertyNames(promises).length;
          for (const promiseName in promises) {
            if (promises.hasOwnProperty(promiseName)) {
              bind(promises[promiseName], promisesSize);
            }
          }
        }
      }),
    ]);

    return $delegate;
  });
});

If I'm not mistaken then implementing .race correctly and adding a snippet like this as an example to the docs (since a function with semantics of .any may in fact be useful) Is slightly better than implementing .any alone.

@petebacondarwin
Copy link
Contributor

We are going to implement $q.race() (because it is part of the ES6 Promise spec) and only document how one could implement one's one version of any() (because it is not part of the spec).

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

No branches or pull requests

4 participants