Angular中使用Http的Observable有哪些好处?

8

从这里开始: https://dev59.com/X1oU5IYBdhLWcg3wg3So#40135509

首先,该答案介绍了Observable如何有助于防止向服务器发送相同重复请求以及如何在许多请求之间暂停,以便服务器不会超载。

然后它说:

就我在Angular中使用Http而言,在正常的用例中,使用Observable与Promise没有太大区别。在实践中,没有一个优点真正相关。希望将来我能看到一些高级用例 :)

我理解的是,在使用Http时,Observable的好处并不是很相关。

为什么会这样?在这种情况下,Http扮演了什么角色?
我需要学习哪个主题才能理解Http在这里的作用?


1
如果你只限制在HTTP领域,你可能是对的。但在现实世界中,你最终会需要拒绝、轮询、事件过滤、事件合并、将组件事件与HTTP服务结合等等,那么你就能品尝到Observables的甜美了。 - Eldar
1
如果你有一个Observable,你可以使用Rxjs进行管理。这样可以让你使用诸如debounce、distinct、delay、pairwise、throttle、timeout、share等操作符:https://www.learnrxjs.io/learn-rxjs/operators/complete。对我来说,Promise和Observable之间存在很大的区别。 - Eliseo
@Eliseo,我想了解Http与Observables效果有什么关系。 OP中的这句话“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.”请解释一下他们谈论的是什么Http。 - Aquarius_Girl
1
想象一下,您调用一个返回“对象”列表的API。 您想为每个对象进行一次调用,以获取“带属性的对象”列表。使用switchMap和forkJoin,您可以订阅并在响应中获取列表。由于Angular是使用可观察对象构建的,因此FormControl.changeValues也是一个可观察对象,您可以再次使用switchMap将输入的更改“转换”为调用API的请求,然后再进行过滤。另外,如果您想要创建一个“加载”,则可以创建一个操作符来显示它。使用Share,您可以避免多次进行相同的调用。 - Eliseo
1
我明白 Observables 拥有很多操作符,但实际上,在大多数情况下,最初只使用 switchMaptakeWhileforkJoin 就足够调用一个 API。 - Eliseo
显示剩余2条评论
6个回答

6
HttpClient返回的observable通常只发出一个值然后完成,表面上看起来很像promise。然而,这样做纯粹是为了一致性和/或者拒绝在Angular中总是使用promises这个想法并不正确。正如其他人所指出的,async pipe支持promise,application init也一样。那么为什么要使用observables而不是promises进行http请求?因为observables提供了另一层抽象。

在你链接的那个线程中,这个评论提出了一个关键点:

@gman确实如此。Promise只表示某些未来的值。它并不代表生成该值的操作。您无法取消值。您无法重试值。它只是一个值。它可能已经存在,也可能不存在,因为发生了异常,但仅此而已。

取消

让我们谈谈取消HTTP请求。在observable的情况下,HttpXhrBackend只是HttpBackend的一个实现,并且通过调用XMLHttpRequest.abort()处理observable的取消:

// 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();
  }
};

请注意,当您使用此 Promise 时,您实际上并不关心它是否使用 XMLHttpRequest,它也可以使用 SomeWhackyAngularXMLHttpRequestThatIsBetter。假设我们返回一个 promise:
// 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();
    });
}

您的客户如何仅通过该Promise取消请求? 您必须执行以下两项操作之一:
  1. 以某种方式公开实现(在本例中为我们的XMLHttpRequest实例)。
  2. 提供您自己的抽象层,在XMLHttpRequest周围(类似于支持中止的httpPromise)中添加另一层抽象来允许取消。

重用

Promise不能被重用。 假设您想使用Promise重试HTTP请求。 您会如何处理? 您需要添加另一层抽象。 在可观察对象的情况下,我们有内置的重试支持

结论

最后值得一提的是,angular HttpClient并不总是返回一个值。 如果将reportProgress设置为true,则会在请求完成时发出多个HttpEvents事件。 有关更多信息,请参见文档。 最后,您应该阅读在Angular存储库中讨论此问题的原始问题,以了解更多背景信息。


3

Angular是建立在RxJs之上的。像EventEmitter这样的异步函数是RxJs observables,表格也是如此。 RxJs非常适合异步功能。由于Angular建立在RxJs之上,因此当他们构建提供http功能的服务时,开发人员会选择使用RxJs。当我们使用RxJs构建异步应用程序时,不会将其与promises混合使用。

如果您只考虑发送请求并获得响应,可能看不出有多大好处,但一旦开始使用RxJs并了解所有的RX operators,就会有所领悟。

在学习Angular之前学习RxJs将使您成为更好的Angular开发人员。我希望几年前有人告诉我这个,因为在我没有完全掌握RxJs的早期日子里编写的应用程序将会有不同的写作方式,如果我花些时间学习RX函数的话。

如果您正在使用observables,则async管道也是另一个非常好的工具,它也可以与promises一起使用,但这意味着您可以直接在模板中使用observables,而无需在代码中管理订阅。


1
请再次阅读问题。我想了解Http与Observables有效性有什么关系。在原始帖子中的这句话“就我在Angular中使用Http而言,在正常使用情况下,使用Observable与Promise相比没有太大区别。” 请解释一下他们在谈论什么http。 - Aquarius_Girl
在学习Angular之前先学习RxJs是一个建议。 - Muhammed Albarmavi
1
顺便说一句,“在学习Angular之前学习RxJs会让你成为一个更好的Angular开发者。”我认真听取了你的建议并开始学习RxJs。谢谢。 - Aquarius_Girl

2
首先,这涉及到一致性。混合使用PromiseObservable并不是一个好主意,您应该始终记住使用了什么和在哪里使用了。
此外,Observable添加了一些在Promises中遗漏的额外功能。让我们将所有帮助您操纵数据的RxJs运算符留在本篇文章之外。 Observable的使用有三个主要优点,比Promise更有益:
  • 重试,Promise无法做到。
  • 节流和防抖可以在一行代码中实现。
  • 取消操作不受原生Promise支持。

1
首先需要提到的是,这只是一种观点。正如您可以在回答评论中读到的那样,有些人同意,有些人不同意。
我能想到的唯一使Http有点特殊的事情是什么? Http Observables总是冷态的。这意味着您只会得到一个结果或错误。这使得Http observables变得相当容易。您可能希望调用端点,可能会稍微修改数据并在屏幕上显示它。
Angular中的其他Observerables,例如form.valueChanges()或routerState都是热态的。这意味着可能会返回多个结果。我可以想象您会使用它们来做更复杂的事情。

冷不意味着只能获得一个结果,冷表示如果没有订阅者,就没有活动。HTTP可观察对象在发出后就会完成,这就是为什么只有一个结果的原因,与热/冷无关。 - Adrian Brand
https://medium.com/@luukgruijs/understanding-hot-vs-cold-observables-62d04cf92e03 - Adrian Brand

1
一个http调用之所以成为Observables的一种特殊情况,是因为一个http调用可以被看作仅发出一个值然后完成或出错的流。

一般来说,Observable流可以发出多个值,可能会完成,也可能会出错。

因此,由于最多只发出一个值,http Observables与Promises非常相似,后者实际上可以发出一个值或错误。

尽管如此,在现实场景中使用Observables进行http调用仍有优势,特别是当您必须将多个http调用与其他异步事件流组合时。在这篇文章中,有一些使用Observables和http调用的典型模式,您可以欣赏rxjs运算符的好处。


0

在我看来,Observables 的关键区别在于它有特权能够取消订阅。而 Promise 则依赖于 Resolve 或 Reject。 使用 Observables 还有许多其他好处,我主要倾向于 Angular。这是一个梦幻般的体验。


请再次阅读问题。我想了解Http与Observables有效性有什么关系。在原始帖子中的这句话“就我在Angular中使用Http而言,在正常使用情况下,使用Observable与Promise相比没有太大区别。” 请解释一下他们在谈论什么http。 - Aquarius_Girl
你的问题描述不够清晰,你想了解什么? 如果你需要了解在Angular中Observables的作用或者http部分,请查看这个网站:https://angular.io/guide/observables-in-angular。 - Malthe
你引用的那个东西不是真的。有很多情况下,你会优先考虑 observables 而不是 promises。(请注意,你引用的是一篇四年前的文章) - Malthe
就我使用 Angular 中的 Http 来说,我只想了解他们为什么在这里谈论 http。 - Aquarius_Girl
@Aquarius_Girl 你是什么意思??不使用Observables处理http会影响效率,需要进行多次调用。你没有定义你的问题与何相关。我只是想了解为什么他们在这里谈论http。- 你没有明确你想知道什么。 - Malthe
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接