Angular:Http vs获取API

rya*_*e28 9 javascript http typescript angular

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

这个:

window.fetch('/api/get_post_by_id/1').then(r => r.json()).then(j => { console.log(j); });
Run Code Online (Sandbox Code Playgroud)

比这更简单:

const obs = this.http.get('/api');
obs.subscribe(() => { ... });
obs.unsubscribe();
Run Code Online (Sandbox Code Playgroud)

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

谢谢!

Dav*_*der 32

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

当我们看一看HttpClient它最初简化了XMLHttpRequest. 与$.ajax最初的做法相同,HttpClient是“角度解决方案”。它遵循一切都是可观察的意识形态,它具有优点(您可以将它与其他可观察对象混合和匹配)和缺点(它会增加很多膨胀)。

的优势 HttpClient

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

的优势 fetch

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

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

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

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

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

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

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

  • 它简化了新人的入职。当您看到诸如

     this.apiService.get('/posts');
    
    Run Code Online (Sandbox Code Playgroud)

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

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

     this.http.get('/posts')
    
    Run Code Online (Sandbox Code Playgroud)

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

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

  • 它已经包含在浏览器中——前提是你不需要支持 7 岁的浏览器——所以它可以导致包的大小略小。

完整的领带

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

结论

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

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

  • @PaulLockwood 很明显,英语对我来说是第二语言,我必须承认我根本没有校对这篇文章。现在很快就浏览完了,但非常欢迎任何和所有的编辑。 (2认同)
  • “它将增加新 Angular 开发人员的学习曲线”这不是优点,而是缺点。在其他条件相同的情况下,更易于用户使用的 API 通常更好。 (2认同)
  • _“它将增加新 Angular 开发人员的学习曲线,从而使你的工作更加特别。”_ - 将此列为优势让我对创建意大利面条式代码感觉良好。 (2认同)

rya*_*e28 9

所以,在使用 Angular 两年后,我发现了以下一些事情:

  1. 有一个名为 RxJS 的库 - https://rxjs-dev.firebaseapp.com/guide/overview,它是用 TypeScript(JavaScript 的超集)编写的。它就像最好的 JavaScript 库之一。

基本上,它通过使用范例使事件驱动的应用程序在 JS 中变得轻而易举Observable。APromise只能返回一次值,并且只能是异步的。Observables 可用于返回单个值或多个值,并且可以是同步或异步的(取决于您如何使用它),您可以添加管道和运算符来转换结果,然后再由订阅者使用/消费等; 它给人一种函数式编程的使用感觉,这很棒。它的功能比承诺的要丰富得多。

Asubscriber监听或“订阅”Observable(.subscribe()对 observable 的调用)。Observable 发出 3 种类型的事件:nexterrorcomplete。Next 表示发出了带/不带数据的事件,error 表示事件流中存在错误,complete 表示事件流已结束,可观察对象将不再发出。

现在,仅仅因为发出了错误,并不意味着事件流停止了。仅当完整事件发生时事件流才会停止。此外,订阅者可以unsuscribe从可观察的对象中获取,这意味着它将停止侦听事件流。

  1. Angular 的服务HttpClient是使用 RxJS 构建的。他们基本上将其包装在旧的 XmlHttpRequest 发出请求的方式上 - https://github.com/angular/angular/blob/main/packages/common/http/src/xhr.ts#L193

当您使用 Angular 的 HttpClient 服务发出请求时,它会自动完成ok响应中的可观察量,因此无需对可观察量调用取消订阅,因为它已经完成了;它不会在错误响应时调用完成,但 http 仅调用响应一次。

  1. Observables 在被订阅之前不会执行;Promise 立即执行。

我想说 Observables 比 Promise 更好用;我不认为 RxJS 会很快或永远离开。


Igo*_*gor 8

this.http.get('/api').subscribe(j => console.log(j)); 
Run Code Online (Sandbox Code Playgroud)

您使它变得太复杂了,上面就是您所需要的,并且它与您所拥有的代码相似window.fetch。您可以使用通用版本,它将被键入到预期的界面中,并使其更加容易。

this.http.get<IModel>('/api').subscribe(j => console.log(j));
Run Code Online (Sandbox Code Playgroud)

不需要,unsubscribe并且如果您想事先转换结果,则只需要pipe+ map。从版本4.3 json()开始,“旧” HttpModule已被调用(技术上已由扩展HttpClient,这是必需的


如果您仍然喜欢Promise而不是Observable,可以随时致电toPromise()

this.http.get('/api').toPromise().then(j => console.log(j)); 
Run Code Online (Sandbox Code Playgroud)

另请参见HttpClient


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

没错,但是有理由不这样做。您可以HttpClient为各种场景,URL,Http动词等注入和编写全面的单元测试。如果window.fetch在整个代码中都使用过相同的操作,则变得更加困难。HttpClient您还可以使用类型系统来获得更丰富的结果。Observables还比Promises具有更多的功能,这在更复杂的场景中会派上用场,例如在处理多个微服务时对呼叫进行排序,或者在收到其他用户输入时取消呼叫。

因此,使用的原因很多,HttpClient除了学习曲线很小之外,我想不出一个。