What are the differences between observables and p

2019-01-31 00:47发布

问题:

So i've read that observables are looking to overtake promises in terms of usage in some of upcoming JavaScript MVC's:

  • Angular 2.0
  • Falcor used by Netflix

What is the difference between observables and promises?

Updated: Apologies! removed my falsy statement.

回答1:

What is the difference between observables and promises?

Simply put: A promise resolves to a single value asynchronously, an observable resolves to (or emits) multiple values asynchronously (over time).

Concrete examples:

  • Promise: Response from an Ajax call
  • Observable: Click events

More information can be found here: http://reactivex.io/intro.html

i've read that observables are looking to overtake promises

Unlikely. Observables might be the better solution to certain problems, but that doesn't make promises obsolete (if that's what you mean).



回答2:

Promises are a representation of 1 future value. Observables are a representation for a possibly infinite amount of values.

Promises will trigger the fetching of that value immediately upon creation. Observables will only start producing values when you subscribe to them. (Unless it's a hot observable, but that's outside the scope of this question)

Promises are designed to represent AJAX calls. Observables are designed to represent anything: events, data from databases, data from ajax calls, (possibly infinite) sequences, etc.



回答3:

Promises offer a very simplistic call back mechanism, where as Rx offers a powerful abstraction over asynchronous programming. An Observable represents a stream of data, which we can then apply operators to in order to define how the incoming data should be treated.

If all you need to do is make an HTTP request and then update a UI component, then using a Promise might suffice.

However, most apps tend to have more complicated needs than that (even if it’s not obvious at the first). Taking our HTTP request for example, let’s see how modelling this as an Observable and using some of the Rx operators can help us:

-If the HTTP request is triggered by a user action, we might want to be wary of firing off multiple HTTP requests (imagine a user typing into a search box). We don’t want to fire a request for every keystroke, so we might want to Throttle our search, so that we only fire a request if the user stops typing for 300ms. Furthermore, if user types a word, waits 300ms, and adds another character, we’ll fire off a subsequent HTTP request. With Promises, we’d probably encounter a race condition as we can’t control the order in which we’ll receive the responses and we can’t cancel old requests. Rx solves this by allowing us to Switch between streams, which calls Dispose on the old request subscriptions we no longer care about. We might also filter out any invalid search inputs, for instance Where the search term is less than 3 characters in length.

-Support for dealing with Timeouts/Error handling. Let’s say our HTTP request fails, Rx allows us to easily Retry making the request.

-Let’s say several parts of our application need to make the same HTTP call, we probably don’t want to actually make the call more than once. We can expose our observable to multiple consumers and use Replay to ensure the call is made once and the result is cached for subsequent subscribers. We can even supply a TimeSpan to Replay, giving us expiring cache behaviour.

-Powerful abstraction over threading through the use of Schedulers, which allows us to control concurrency. Even better, we can use Test Schedulers in our Unit Tests to control time, allowing us to simulate Timeouts, race conditions etc.

These are some quick examples to demonstrate what is possible. There are many more operators within the Rx framework to cater for all types of scenarios and the composability of Rx means you can easily combine operators to define the behaviour you need. It’s also easy to create your own reusable operators (e.g. RetryAfterDelay).

In summary, Rx can do everything than Promises can do, and far far more. I suspect in the next couple of years there'll be a continued shift towards Rx instead of Promises.

For further reading, I'd recommend taking a look at the section on Observables in the Angular 2 guide.



回答4:

as said in Angular 2 guid

Converting to a Promise is often a good choice when you want to fetch a single chunk of data. so When you receive the data, you're done.

But in some cases requests aren't always done only once. You may start one request, cancel it, and make a different request before the server has responded to the first request.

for example in a search component As the user types a name into a search box, you'll make repeated HTTP requests by that search query.

A request-cancel-new-request sequence is difficult to implement with Promises, but easy with Observables.

so if your component gets data with only one request it's a good choice to use Promise but if it has a chain of request-cancel-new request you should use observable



回答5:

Observables are often compared to promises. Here are some key differences:

Observables are declarative; computation does not start until subscription. Promises execute immediately on creation. This makes observables useful for defining recipes that can be run whenever you need the result.

Observables provide many values. Promises provide one. This makes observables useful for getting multiple values over time.

Observables differentiate between chaining and subscription. Promises only have .then() clauses. This makes observables useful for creating complex transformation recipes to be used by other part of the system, without causing the work to be executed.

Observables subscribe() is responsible for handling errors. Promises push errors to the child promises. This makes observables useful for centralized and predictable error handling.

Best explanation by angular on official website :

https://angular.io/guide/comparing-observables



回答6:

When you understand Observables correctly, the differences to Promises are pretty obvious.

The best way to demystify a convoluted concept is to implement it from scratch. Here is an almost purely functional Observable implementation and an example, that wouldn't work with Promises:

/*** Observable type ***/

// type constructor (of a product type)

const proType = name => cons => {
  const f = (k, ...args) =>
    Object.defineProperties({["run" + name]: k}, {
      [Symbol.toStringTag]: {value: name},
      [Symbol("args")]: {value: args}
    });

  return cons(f);
};

// value constructor

const Observable = proType("Observable")
  (Observable => k => Observable(k));

/*** Observer factory ***/

const Observer = observer => {
  let isUnsubscribed = false;

  return {
    next: function(x) {
      if (isUnsubscribed)
        throw new Error("unsubscribed");

      else {
        try {
          return observer.next(x);
        }

        catch(e) {
          isUnsubscribed = true;
          this.cancel();
          throw e;
        }
      }
    },

    error: function(e) {
      if (isUnsubscribed)
        throw new Error("unsubscribed");

      else {
        try {
          return observer.error(e);
        }

        catch(e_) {
          isUnsubscribed = true;
          this.cancel();
          throw e_;
        }
      }
    },

    complete: function() {
      if (isUnsubscribed)
        throw new Error("unsubscribed");

      else {
        try {
          const r = observer.complete();
          this.cancel();
          return r;
        }

        catch(e) {
          isUnsubscribed = true;
          cancel();
          throw e;
        }
      }
    }
  };
};

/*** combinators + auxiliary functions ***/

const subscribe = observable => handlers => {
  const observer = Observer(handlers),
    cancel = observable.runObservable(observer);

  observer.cancel = cancel;
  return cancel;
};

const obsMap = f => observable =>
  Observable(observer => {
    const mapObserver = {
      next: x => observer.next(f(x)),
      error: e => observer.error(e),
      complete: () => observer.complete()
    };

    return observable.runObservable(mapObserver);
  });

/*** main ***/

// create an Observable instance

const numStream = Observable(observer => {
  let i = 0;

  const timer = setInterval(() => {
    observer.next(i++);
  }, 1000);
  
  return () => clearTimeout(timer);
});

// map a function over it

const squaredNumStream =
  obsMap(x => x * x) (numStream);

// run the observable

const cancel = subscribe(squaredNumStream) ({
  next: x => console.log(x),
  error: e => console.error(e),
  complete: () => console.log("finished")
});

// cancel it

setTimeout(cancel, 11000);

In the example above the Observable squaredNumStream emits a stream of theoretically infinite values asynchronously. You cannot do this with Promises, because they represent a single future value.

I could have easily subscribed to another squaredNumStream without both instances interfering with each other. This is because Observables are unicast, whereas Promises are multicast.

squaredNumStream doesn't run at declaration time, but only after subscription, because Observables are lazily evaluated. Promises on the other hand are eagerly evaluated that is, they start running as soon as you create them.

And finally, Observables are cancelable by design, whereas Promises are hard to cancel due to there unicast semantics.