简体   繁体   中英

Benefits of Observable with Http in Angular

From here: https://stackoverflow.com/a/40135509/462608

First this answer describes how Observables are helpful in preventing same repeated requests to the server and how we can pause between many requests so that the server doesn't get overloaded.

They it says:

As far as I am using Http in Angular, I agree that in the normal use cases there is not much difference when using Observable over Promise. None of the advantages are really relevant here in practice. Hope I can see some advanced use case in the future:)

What I understand here is that when Http is used then Observables benefits are not really relevant.

Why is that so? What role is played by Http in this case?
What topic do I have to study to understand Http's role here?

The observable that HttpClient returns usually only emits one value then completes which, on the surface seems a lot like a promise. However, the idea that it is purely for consistency and/or that promises are always eschewed in Angular isn't true. As others have noted, the async pipe supports promises as does application init . So why use observables instead of promises for http requests? Because observables offer another layer of abstraction.

In that thread you linked, this comment makes a crucial point:

@gman Exactly. The Promise simply represents some future value. It does not represent the operation which generates the value. You cannot cancel a value. You cannot retry a value. It's just a value. It may or may not be present yet, and it may never exist because an exception occurred, but that's it.

Cancellation

Let's talk about cancelling a HTTP request. In the case of the observable, HttpXhrBackend is just one implementation of HttpBackend and handles the cancellation of the observable by calling XMLHttpRequest.abort() :

// This is the return from the Observable function, which is the
// request cancellation handler.
return () => {
  // On a cancellation, remove all registered event listeners.
  xhr.removeEventListener('error', onError);
  xhr.removeEventListener('load', onLoad);
  if (req.reportProgress) {
    xhr.removeEventListener('progress', onDownProgress);
    if (reqBody !== null && xhr.upload) {
      xhr.upload.removeEventListener('progress', onUpProgress);
    }
  }

  // Finally, abort the in-flight request.
  if (xhr.readyState !== xhr.DONE) {
    xhr.abort();
  }
};

Note that when you're consuming this promise, you don't actually care that it's using XMLHttpRequest and it could be using SomeWhackyAngularXMLHttpRequestThatIsBetter . Let's say we return a promise instead:

// How would something that consumes this call xhr.abort()?
function myHttpGetPromise(method, url) {
    return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url);
        xhr.onload = resolve;
        xhr.onerror = reject;
        xhr.send();
    });
}

How could your client cancel the request with just that promise? You would have to either:

  1. Somehow expose the implementation (our XMLHttpRequest instance in this case).
  2. Provide your own layer of abstraction around the XMLHttpRequest (something like httpPromise which supports abort) to allow for cancellation.

Re-use

Promises are not re-usable. Let's say you want to retry an HTTP request using promises. How would you do it? You guessed it: you would have to add another layer of abstraction. In the case of observables, we have retry support out of the box.

Conclusion

One thing worth mentioning in closing is that the angular HttpClient doesn't always just return one value. In the case where you set reportProgress to true, it emits multiple HttpEvents before finally completing when the request is complete. See the docs for more info. And finally, you should read the original issue where this was debated in the Angular repo for some backstory.

Angular is built upon RxJs. Async functions like the EventEmitter are RxJs observables, forms. RxJs is great for asynchronous functionality. Seeing that Angular is built upon RxJs when they are building a service that provides http functionality the devs are going to choose RxJs. When we build an asynchronous app with RxJs we don't mix it with promises.

It might not look like there is much benefit when you just think about sending a request and getting a response but once you start working with RxJs and understand all the RX operators it clicks.

Learning RxJs before you learn Angular will make you a much better Angular dev. I wish somebody told me this a few years ago because the apps I wrote in the early days where I didn't quite fully grok RxJs would have been written quite differently if I spent some time learning the RX functions.

The async pipe is also a another great tool if you are using observables, it does work with promises as well, but it means you can use observables directly in your templates with having to manage subscriptions in the code.

First of all, it's about consistency. That's not a good idea to mix Promise and Observable , you should always remember what and where you have used.

Also Observable add some extra features that missed in Promises . Let's leave all RxJs operators that help you manipulate data out of this post's scope.

There are three main points of Observable usage, that give more benefit rather than Promise :

  • Retries that are not doable by Promise .
  • Throttling and debouncing can be implemented in one line.
  • Cancelation that is not supported by vanilla Promise ,

The first thing that should be mentioned is that it is an opinion. As you can read in the answer comment, some people agree and some people disagree.

There is only one thing I can think of that makes Http kinda special??. Http Observables are always cold. That means you get only one result or an error. That makes Http observables kinda easy. You probably want to call the endpoint maybe modify the data a little and show it on the screen.

Other Observerables in Angular such as the form.valueChanges() or the routerState are hot. That means multiple results MAY come back. I can imagine you would do more complex things with that.

What makes an http call sort of a special case for Observables is that an http call can be seen as a stream which either emits just one value and then completes or it errors .

Observable streams in general can emit more than one value, may or may not complete, may or may not error.

So for this reason, ie at most one value emitted, http Observables are close to Promises, which can actually emit just one value or error.

N.netheless there are advantages in using Observables for http calls in real life scenarios, specifically when you have to compose multiple http calls with other async streams of events. In this article there are some typical patterns of use of Observables with http calls where you can appreciate the benefits of rxjs operators.

The key difference in my opinion is how Observables has the privilege of being able to cancel subscriptions. Promises is relying on having either to Resolve or Reject. There is so many other good advantages of using Observables too, and I primarily tend to Angular. It's a dreamland.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM