【问题标题】:Benefits of Observable with Http in AngularAngular 中使用 Http 的 Observable 的好处
【发布时间】:2020-12-07 06:53:55
【问题描述】:

从这里:https://stackoverflow.com/a/40135509/462608

首先,这个答案描述了 Observables 如何有助于防止向服务器发送相同的重复请求,以及我们如何在多个请求之间暂停,以免服务器过载。

他们说:

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

我在这里的理解是,当使用 Http 时,Observables 的好处并不真正相关。

为什么会这样?在这种情况下 Http 起什么作用?
我必须研究什么主题才能理解 Http 在这里的作用?

【问题讨论】:

  • 好吧,如果您将区域限制为 HTTP,您可能是对的。但在现实场景中,最终还是需要谴责、轮询、事件过滤、事件合并、将组件事件与 HTTP 服务结合等。然后你就可以尝到 observables 的甜头了。
  • 如果你有一个 Observable,你可以使用 Rxjs 来管理。这允许您将运算符用作去抖动、不同、延迟、成对、节流、超时、共享...:learnrxjs.io/learn-rxjs/operators/complete。对我来说,Promise 和 Observable 之间有很大的区别
  • @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是什么。
  • 假设您调用一个返回“对象”列表的 API。您想对每个对象进行一次调用以获取“具有属性的对象”列表。使用 switchMap 和 forkJoin 订阅并获得列表的响应。因为 Angular 是用 observables 制作的。 FormControl.changeValues 是一个可观察的,您可以再次使用 switchMap 将调用中的输入更改“转换”为 API,从而为您提供结果,您可以在调用之前进行过滤。另一个,你想做一个“加载”。您可以创建一个运算符来显示它。使用 Share,您可以避免多次拨打同一个电话。
  • 我知道 Observables 有太多的运算符,但实际上,一开始使用 switchmaptakeWhileforkjoin 在大多数情况下都足以调用 API

标签: angular http rxjs observable angular-promise


【解决方案1】:

HttpClient 返回的 observable 通常只发出一个值然后完成,表面上看起来很像一个承诺。然而,纯粹是为了一致性和/或在 Angular 中总是回避承诺的想法是不正确的。正如其他人所指出的,async pipeapplication init 一样支持承诺。那么为什么对 http 请求使用 observables 而不是 Promise 呢?因为 observable 提供了另一层抽象。

在您链接的那个帖子中,this comment 提出了一个关键点:

@gman 没错。 Promise 只是代表一些未来的价值。它不代表生成值的操作。您不能取消值。您不能重试一个值。这只是一个值。它可能存在也可能不存在,也可能因为发生异常而永远不存在,但仅此而已。

取消

让我们谈谈取消 HTTP 请求。在 observable 的情况下,HttpXhrBackend 只是通过调用XMLHttpRequest.abort() 实现的HttpBackendhandles the cancellation of the 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();
  }
};

请注意,当您使用此承诺时,您实际上并不关心它使用的是XMLHttpRequest,它可能使用的是SomeWhackyAngularXMLHttpRequestThatIsBetter。假设我们返回一个承诺:

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

您的客户怎么可能仅凭这个承诺就取消请求?您必须:

  1. 以某种方式公开实现(在本例中是我们的 XMLHttpRequest 实例)。
  2. 围绕XMLHttpRequest(类似于支持中止的httpPromise)提供您自己的抽象层以允许取消。

重复使用

Promise 不可重复使用。假设您想使用 Promise 重试 HTTP 请求。你会怎么做?您猜对了:您将不得不添加另一层抽象。对于 observables,我们有开箱即用的 retry support

结论

结束时值得一提的是,角度 HttpClient 并不总是只返回一个值。在将reportProgress 设置为true 的情况下,它会在请求完成时最终完成之前发出多个HttpEvents。请参阅the docs 了解更多信息。最后,您应该阅读 Angular 存储库中的 the original issue where this was debated 了解一些背景故事。

【讨论】:

    【解决方案2】:

    使 http 调用成为 Observables 的一种特殊情况的原因在于,http 调用可以被视为一个流,它要么只发出一个值然后完成,要么出错

    Observable 流通常可以发出多个值,可能会或可能不会完成,可能会或可能不会出错。

    因此,由于这个原因,即最多发出一个值,http Observables 接近于 Promises,它实际上只能发出一个值或错误。

    尽管如此,在现实生活场景中使用 Observables 进行 http 调用还是有优势的,特别是当您必须将多个 http 调用与其他异步事件流组合时。在this article 中,有一些典型的通过 http 调用使用 Observables 的模式,您可以从中体会到 rxjs 运算符的好处。

    【讨论】:

      【解决方案3】:

      首先,这是关于一致性。将PromiseObservable 混合使用不是一个好主意,您应该始终记住您使用过的内容和位置。

      Observable 添加一些在 Promises 中遗漏的额外功能。让我们把所有帮助您操作数据的 RxJs 运算符都放在本文的范围之外。

      Observable 使用的三个要点,比Promise 带来更多好处:

      • Promise 无法重试。
      • 可以在一行中实现节流和去抖动。
      • vanilla Promise 不支持取消,

      【讨论】:

        【解决方案4】:

        首先应该提到的是它是一种观点。正如您在答案评论中看到的那样,有些人同意,有些人不同意。

        我能想到的只有一件事让 Http 有点特别???。 Http Observables 总是冷的。这意味着您只会得到一个结果或错误。这使得 Http observables 有点容易。您可能想调用端点,可能会稍微修改数据并将其显示在屏幕上。

        Angular 中的其他 Observerables,例如 form.valueChanges() 或 routerState 是热的。这意味着可能会返回多个结果。我可以想象你会用它做更复杂的事情。

        【讨论】:

        • 冷并不意味着你只能得到一个结果,冷意味着如果没有订阅者就没有活动。 Http 可观察对象一旦发出就完成,这就是为什么只有一个结果。与热/冷无关。
        【解决方案5】:

        在我看来,主要区别在于 Observables 如何有权取消订阅。 Promises 依赖于 Resolve 或 Reject。 使用 Observables 还有很多其他优点,我主要倾向于 Angular。这是一个梦境。

        【讨论】:

        • 请再次阅读问题。我想了解 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是什么意思。
        • 您的问题描述不正确,您想知道什么?如果您需要了解 Observables 在 Angular 或 http 部分中的作用 - 去研究这个网站angular.io/guide/observables-in-angular
        • 我在上面的评论中强调了这句话。我想了解它的含义。
        • 你引用的东西,不是真的。在许多用例中,您会优先考虑可观察对象而不是承诺。 (请注意您指的是 4 年前的帖子)
        • As far as I am using Http in Angular我只是想明白他们为什么在这里谈论http。
        【解决方案6】:

        Angular 是基于 RxJs 构建的。像 EventEmitter 这样的异步函数是 RxJ 的 observables 和表单。 RxJs 非常适合异步功能。看到 Angular 在构建提供 http 功能的服务时构建在 RxJs 之上,开发人员将选择 RxJs。当我们使用 RxJs 构建异步应用程序时,我们不会将它与 Promise 混合使用。

        当您只是考虑发送请求并获得响应时,看起来可能没有太多好处,但是一旦您开始使用 RxJs 并了解它所点击的所有 RX 运算符。

        在学习 Angular 之前学习 RxJs 将使您成为更好的 Angular 开发人员。我希望有人在几年前告诉我这一点,因为如果我花一些时间学习 RX 功能,我在早期编写的应用程序(我没有完全了解 RxJs)会完全不同。

        如果您使用 observables,异步管道也是另一个很棒的工具,它也适用于 Promise,但这意味着您可以直接在模板中使用 observables,而无需在代码中管理订阅。

        【讨论】:

        • 请再次阅读问题。我想了解 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是什么。
        • Learning RxJs before you learn Angular 是一个??建议??
        • 顺便说一句,Learning RxJs before you learn Angular will make you a much better Angular dev. 我已经认真对待您的建议,并开始学习 RxJs。谢谢。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-02-02
        • 2018-12-05
        • 1970-01-01
        • 2021-11-08
        • 2018-01-07
        • 1970-01-01
        • 2019-07-14
        相关资源
        最近更新 更多