角度:Http 与获取 API

新手上路,请多包涵

虽然我了解 Angular 发出 HTTP 请求的方式,但我更喜欢使用内置的 Fetch API,因为我不必为了发出 1 个简单请求而订阅和取消订阅。我尝试在我的角度应用程序中使用它,它没有抛出任何错误,页面没有重新加载(仍然是 SPA),一切正常。我想一切都有时间和地点。

这个:

 fetch('/api/get_post_by_id/1').then(r => r.json()).then(j => { console.log(j); });

比这更简单:

 const obs = this.http.get('/api');
obs.subscribe(() => { ... });
obs.unsubscribe();

基本上我的问题是,在开发 Angular 应用程序时使用 Fetch API 是错误的吗?

原文由 ryanwaite28 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 258
2 个回答

就像您在开发过程中遇到的任何工具一样,每个工具都有优点和缺点,最好考虑一下为什么要使用一个工具。

当我们看一下 HttpClient 它最初简化了 XMLHttpRequest 的混乱。以同样的方式 $.ajax 最初是这样做的, HttpClient 是“角度解决方案”。它遵循一切皆可观察的意识形态,它有优点(你可以将它与其他可观察物混合搭配)和缺点(它增加了很多膨胀)。

HttpClient

  • 它允许轻松混合和匹配两个 observable(例如,假设您有一个返回多次的 observable 和一个返回一次的 API 请求,并且您想将两者压缩在一起,这很容易做到)。当然,将 promise 变成 observable 只需要从 from 导入 rxjs
  • 如果您忘记添加抽象 - 让所有请求都经过 apiService 层 - 您仍然可以使用拦截器神奇地获得类似的结果。
  • 它将增加新的 Angular 开发人员的学习曲线,从而使您的工作更加特别。
  • HttpClient 为您做了一些魔术,例如自动重试请求。
  • 它已经包含在 Angular 中,所以如果你需要支持像 IE11 这样的 7 年前的浏览器,你不需要加载像 fetch 这样的 polyfill。

fetch

重要提示:所有与获取相关的代码都假定您确实创建了一个非常简单的抽象(例如这些示例中的 apiService )。这与在 HttpClient 中设置拦截器是一样的。

  • 这是新的行业标准。一旦你知道它,它就可以在任何地方使用(很可能一旦 Angular 和 React 消亡 - 在某个时候它们会 - fetch 仍然很可能存在)。

  • 它简化了服务工作者的工作,因为 RequestResponse 对象与您在普通代码中使用的对象相同。

  • HTTP 请求通常会返回一次且仅返回一次(当然,您可能会逐块加载文件,但这是规则中非常罕见的例外)。 fetch 是围绕规范(单个返回值)构建的,而不是异常(多个返回值),因此返回 Promise 而不是流式类型。这样做的好处是它可以很好地与任何和所有相关的新语言功能一起使用,例如 asyncawait 。相比:

    try {
       const posts = await this.apiService.get('/posts');
       // work with posts
   } catch (error) {
       // handle error
   }
   console.log('this happens **after** the request completes');

   this.http.get('/posts')
       .subscribe(posts => {
           // work with posts
       })
       .catch(error => {
           // work with error
       });
   console.log('this happens **before** the request completes');

(当然你也可以 toPromise 每个将完成的 Observable(或添加 .pipe(take(1)) ,但坦率地说,这是一堆多余的代码(我仍然经常最终使用))

  • 它简化了新人的入职。当您看到这样的请求时
   this.apiService.get('/posts');

来自任何框架的开发人员都可以来并右键单击 .get 并查看函数定义,其中将明确定义域和要添加的身份验证标头等内容。

另一方面,当开发人员看到

   this.http.get('/posts')

除非他们知道 Angular 特定的魔法,否则他们无法轻易发现请求是否以及在何处可能会发生变化。这就是为什么 Angular 被认为具有陡峭的学习曲线的原因之一。

  • 不存在您不知道的魔术的风险,例如自动重试请求,这些请求最终可能会在同一请求中在服务器上触发 4 次,而您不知道这怎么可能。

  • 它已经包含在浏览器中——前提是您不需要支持 7 年前的浏览器——所以它可以导致包大小稍微小一些。

完整领带

  • 我真的看不出类型有什么不同,因为可以从任何方法中输入返回值。 <Model>this.apiService.get('/posts') 工作得很好。

结论

就个人而言,我强烈建议任何人使用带有抽象层的 fetch 。它使代码更容易阅读(即使是从未见过 asyncawait 初级人员也能够阅读它),即使你处于一种罕见的情况下 apiService 必须返回多次你仍然完全可以自由地这样做,因为你完全在控制之中。通常,只有在替代方案具有显着优势时,您才 不应 使用标准 ( fetch )。即使就优点和缺点而言它是完美的结合,它可能也不值得为“特定于框架”的解决方案而努力。

HttpClient 除了在不需要为 API 请求设置抽象层的初始项目设置期间节省几分钟时间之外,似乎没有提供任何有形优势。

原文由 David Mulder 发布,翻译遵循 CC BY-SA 4.0 许可协议

this.http.get('/api').subscribe(j => console.log(j));

你把它弄得太复杂了,以上就是你所需要的,它类似于你为 window.fetch 编写的代码。您可以使用通用版本,它也将被输入到预期的界面,从而使它变得更加容易。

 this.http.get<IModel>('/api').subscribe(j => console.log(j));

不需要 unsubscribe 你只需要 pipe + map 如果你想事先转换结果。调用 json() 是“旧”HttpModule 所必需的,它已被替换为( _技术上扩展为_) HttpClient 从版本 4.3 开始


如果你仍然喜欢 Promise 而不是 Observable 你可以随时调用 toPromise()

 this.http.get('/api').toPromise().then(j => console.log(j));

另见 HttpClient


开发 Angular 应用程序时使用 Fetch API 是错误的吗?

这没有错,但有理由不这样做。您可以注入 HttpClient 并为各种场景、URL、Http 动词等编写综合单元测试。如果您在整个代码中使用了 window.fetch 那么这样做会变得更加困难。 HttpClient 也更丰富,您可以为结果使用类型系统。 Observable 的功能也比 Promises 更丰富,这在更复杂的场景中会派上用场,比如在处理多个微服务时对调用进行排序,或者在收到额外的用户输入时取消调用。

因此,使用 HttpClient 有多种原因,除了它是一个小的学习曲线之外,我想不出一个理由。

原文由 Igor 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题