Observable with Http 在 Angular 中的优势

Benefits of Observable with Http in Angular

从这里开始:

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

他们说:

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 :)

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

为什么会这样? Http在这种情况下起到什么作用?
我需要学习什么主题才能理解Http在这里的作用?

Angular 建立在 RxJs 之上。像 EventEmitter 这样的异步函数是 RxJs 可观察对象,形式。 RxJs 非常适合异步功能。看到 Angular 是建立在 RxJs 之上的,当他们构建提供 http 功能的服务时,开发人员将选择 RxJs。当我们使用 RxJs 构建异步应用程序时,我们不会将其与 promises 混合使用。

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

在学习 Angular 之前学习 RxJs 会让你成为更好的 Angular 开发者。我希望几年前有人告诉我这一点,因为如果我花一些时间学习 RX 函数,我在早期编写的应用程序会完全不同,当时我并没有完全理解 RxJs。

如果您使用可观察对象,异步管道也是另一个很棒的工具,它也适用于承诺,但这意味着您可以直接在模板中使用可观察对象,而不必在代码中管理订阅。

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

首先应该提到的是,这是一个意见。正如您在答案评论中看到的那样,有人同意有人不同意。

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

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

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

Observable 添加了一些 Promises 中遗漏的额外功能。让我们将所有帮助您操作数据的 RxJs 运算符留在此 post 的范围之外。

Observable 用法有三个要点,比 Promise 有更多好处:

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

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

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

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

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

观察到 HttpClient returns 通常只发出一个值然后完成,表面上看起来很像一个承诺。但是,在 Angular 中始终回避承诺纯粹是为了保持一致性 and/or 的想法是不正确的。正如其他人所指出的,async pipe supports promises as does application init。那么为什么要对 http 请求使用 observable 而不是 promises 呢?因为可观察对象提供了另一层抽象。

在您链接的那个线程中, 提出了一个关键点:

@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.

取消

我们来谈谈取消 HTTP 请求。对于可观察对象,HttpXhrBackend 只是 HttpBackendhandles the cancellation of the observable 的一种实现方式,通过调用 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();
  }
};

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

// 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 )以允许取消。

Re-use

承诺不是 re-usable。假设您想使用 promises 重试 HTTP 请求。你会怎么做?您猜对了:您将不得不添加另一层抽象。对于 observables,我们开箱即用 retry support

结论

最后值得一提的是 angular HttpClient 并不总是 return 一个值。在您将 reportProgress 设置为 true 的情况下,它会在请求完成时最终完成之前发出多个 HttpEvents 。有关一些背景故事,请参阅 Angular 存储库中的 the docs for more info. And finally, you should read the original issue where this was debated