欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

宁皓网 Angular:HTTP 有大用

在 AppModule 模块里导入 HttpClientModule,我们就可以在任何地方使用这个模块里提供的 Http 客户端了,使用这个东西可以去请求服务端应用的接口,去获取到需要的数据。

   我们会准备一个演示用的服务端应用,里面添加一个内容接口,然后配置 Angular 使用这个 Http 客户端。使用这个客户端上的 get 方法,去请求服务端应用的内容列表数据。

   请求服务端的时候,可能会遇到各种错误,我们会再了解几个处理这些错误用的方法。

   封面摄影:alfonso maseda varela

来自 https://ninghao.net/course/7755#info


# git branch        #查看项目当前分支

# git log                #查看当前分支上提交的日志

# git checkout master            #切换到master分支

# git merge observable                #合并observable分支到当前分支

# git log                #查看当前分支上提交的日志

# git checkout -b http                #创建http分支并切换到http分支.

# git push origin master observable http                #推送几个分支到远程origin

相当于 执行如下几个命令:

# git push origin master

# git push origin observable 

# git push origin http  


# git remote -v                #查看远程


# npm install json-server --save-dev                    #安装json-server,--save-dev表示保存在项目的开发依赖里面

  (相当于 yarn add json-server -dev )

  (npm install json-server --save-dev --port 3333) 改成其它的端口




介绍与准备

1)介绍(HTTP)

在 AppModule 模块里导入 HttpClientModule,我们就可以在任何地方使用这个模块里提供的 Http 客户端了,使用这个东西可以去请求服务端应用的接口,去获取到需要的数据。

我们会准备一个演示用的服务端应用,里面添加一个内容接口,然后配置 Angular 使用这个 Http 客户端。使用这个客户端上的 get 方法,去请求服务端应用的内容列表数据。

请求服务端的时候,可能会遇到各种错误,我们会再了解几个处理这些错误用的方法。

来自  https://ninghao.net/video/7744#info


2)准备项目(HTTP)


查看一下项目当前的分支,

# git branch 

显示是在 observable 这个分支上,检查一下在这个分支上做的提交,

 git log

最后一次提交是 Fix bug 。把项目当前分支切换到 master,

# git checkout master

然后在这个分支上做一次合并,要合并的是 observable 分支。

# git merge observable 

合并之后检查一下分支上的提交,

 git log

最后一次提交是 Fix bug 。下面可以再去创建一个新的分支并且切换到这个新的分支,名字是 http 。

# git checkout -b http

再把本地的几个分支推送到 origin 远程,要推送的是 master,observable,还有 http 。

# git push origin master obervable http

这个课程我对项目的修改都会保存在 http 这个分支上,到时候你可以找到项目的远程,

# git remote -v

然后查看一下我在这个分支上做的提交。

我一直在 master 分支上工作

来自  https://ninghao.net/video/7745


3)准备一个演示用的后端服务


Angular 应用可以请求后端服务接口,获取到需要的数据,或者把前端上的数据交给后端服务去处理。这个后端服务接口需要单独去开发,可以使用一些服务端的应用框架去开发。这里我们先准备一个简单的,专门用来测试用的服务端应用接口。

可以先给我们的项目安装一个东西,在项目的下面,执行 npm install 安装一个 json-server ,加上 --save-dev ,把它保存在项目的开发依赖里面。

# npm install json-server --save-dev

完成以后回到项目,打开项目的 package.json 文件,在 scripts 里面,可以再添加一条命令,命令可以是 start:devserver,要执行的是,用一下刚才安装的 json-server ,加上一个 watch 选项,然后是一个 json 文件,可以用一下 service 下面的 db.json。

下面可以再去准备一下这个 json 文件。在项目下面,创建一个文件,放在 service 里面,名字是 db.json。这个文件有点像是我们创建的服务端接口的数据库。

一组大括号,里面添加一个 posts ,它是一个数组,里面可以再添加一些数据项目。我提前准备好了一些数据项目,可以把它们粘贴到这里。

每个数据项目里面,都有一个 id,title,body 还有一个 image 属性。

回到终端,在项目下面,执行一下 npm run start:devserver,

#  npm run start:devserver  ( 或者  #  json-server --watch ./service/db.json )

这样就会运行这个演示用的服务端。地址是 localhost:3000 。

如果运行这个命令的时候,提示端口被占用了,可以修改一下这个命令,在 json-server 命令里面用一下 --port 选项,设置要使用的端口号,比如 3333 或者其它的端口。

(   json-server --watch ./service/db.json --port 3333 )

打开浏览器访问一下 localhost:3000,现在我们的这个服务端应用里面只有一个接口,就是这个 posts,打开它,返回的就是一组内容项目。

回到项目,可以做一次提交,打开编辑器的源代码管理功能,选中要提交的修改,输入提交日志,Prepare a fake backend.

把这次提交推送到项目的远程。

刚才创建演示用的服务接口的时候,用到了一个 db.json 文件,这个文件已经包含在刚才我做的那次提交里了,你可以打开这个项目的远程。可以切换到 http 这个分支,在这个分支的 service 下面,你会看到这个 db.json 文件。 复制一下这个文件的内容,然后可以在自己的项目里去创建一个一模一样的服务端。

来自  https://ninghao.net/video/7746#info


4)清理 PostService 服务


访问应用的 posts,页面上会显示一组内容,这里用了一个 PostComponent 组件,回到项目,打开 PostComponent 组件,界面上显示的内容列表需要的数据就是这个组件里的 entities 属性的值。这个值我们在构造方法里面使用 postService 服务上的 index 方法获取到的。

打开 PostService 服务,这个服务里有个 index 方法,它的功能就是返回了一组同步的数据,这个数据实际上来自一个文件,就是这个 posts 。

下面我们会使用应用的 Http 客户端,请求服务端应用接口异步的获取到需要的数据,可以先清理一下这个服务,去掉 entities 属性,去掉构造方法里的这行代码,index 方法里的代码,还有 show 这个方法的代码,这个方法是返回单个内容资源的时候用的一个方法。

回到浏览器预览一下,你会发现页面上现在就没有要显示的内容了。

来自    https://ninghao.net/video/7747#info


HTTP 客户端

5)配置 Http 客户端


之前我们准备好了一个演示用的服务端应用,里面有一个 posts 接口,下面可以先用一个 Http 客户端去请求一下这个接口试试。我用的是 Insomnia ,新建一个请求,请求的方法使用 HTTP 的 GET 方法,地址是 http://localhost:3000/posts ,发送一下这个请求。

服务端那里收到了这个请求以后,会给我们响应回来一些数据,这些数据就是服务端应用的 posts 这个接口返回的。

在 Angular 应用里,也可以使用框架里提供的 Http 客户端,去请求服务端接口获取到数据。先去准备一下这个 Http 客户端。

HttpClientModule

一般我们会在应用的 AppModule 模块里,导入 HttpClientModule 模块,先在文件顶部导入它,来自 @angular/common/http,需要的是 HttpClientModule 。

然后在模块的 imports 里面,添加一个 HttpClientModule 。

HttpClient

这样我们就可以在应用的其它地方,使用这个 HttpClientModule 里的 HttpClient 请求服务端应用获取到数据了。

打开应用里的 modules,post,services 里的 PostService,在这个服务里可以用一下 HttpClient,把它作为这个类的依赖注入进来,在构造方法的参数里,添加一个 private http,类型是 HttpClient ,这个 HttpClient 来自 @angular/common/http 。

来自   https://ninghao.net/video/7749#toc

6)用 Http 客户端请求获取数据


在 PostService 里面,已经注入了 HttpClient 这个依赖,名字叫 http,现在就可以使用这个 Http 客户端上的一些方法去请求服务端接口了。

index()

在这个 index 方法里面,让它 return this.http,用一下 Http 客户端上的 get,请求一下服务端接口,在这个服务里,可以添加一个属性,名字是 postsApi,设置一下它的值 http://localhost:3000/posts 。

把 this.postApi 交给 HttpClient 上面的 get 方法。这个方法返回的值是一个 Observable 。

Post 组件

下面再打开 Post 组件,在这个组件里可以用一下 PostService 上的 index 方法。 在组件的构造方法里,用了一下这个方法,把方法返回的值交给了 this.entities。 先去掉这行代码。

然后在组件的 ngOnInit 方法里面,添加一个 entities$,一般 Observable 的名字的最后都会带一个 $ 后缀。它的值用一下 this.postService 上的 index 方法。

这个 entities$ 是个 Observable,下面用一下它上面的 subscribe 订阅一下这个 Observable,提供一下方法,这个 Observable 上生产出来的数据的名字可以叫 data,类型是一组 Post。

这个 Observable 生产出来的数据就是请求服务端接口得到的响应数据。在这个方法里,设置一下 this.entities 的值,让它等于这个 data 。

预览

回到浏览器先预览一下,你会发现,页面上会现在会显示一组内容,这组内容数据是用 HttpClient 请求服务端接口返回来的。

图片

回到项目,打开 PostComponent 组件的视图,这里用了一个 PostItem 组件。在项目里找到这个组件的视图文件,打开以后,可以在这个视图里再添加一个图片元素。放在这个标题的下面,一个 img 标签。给它绑定一个 src 属性,它的值应该是数据项目里的 image 属性的值,这里并没有提示可以使用 image 属性。

可以再修改一下,打开 post/models 里的这个 post.model.ts,在这个类里面,再添加一个参数属性。名字是 image ,可以是个可选的属性,类型是 string 。

然后回到 PostItemComponent 组件的视图,这次这里就会提示数据项目里面可以使用 image 属性了。

后面再绑定一个 alt 属性,值是 entity 里的 title 。

再打开这个组件的样式表,这里可以设置一下图像元素的样式,把它的 width ,也就是宽度值设置成 100% 。

然后回到浏览器可以预览一下现在的这个内容列表。现在每个列表项目里面都会出现我拍的一张照片。

来自   https://ninghao.net/video/7750#info


7)请求单个内容资源


点击内容列表里的一个内容项目的标题,会打开这个内容详情页面。显示这个内容详情用的是 PostDetailsComponent 组件。回到项目,打开这个组件。

组件视图里用的数据是这个组件里的 entity,这个数据我们之前用了一个 Resolver 提前获取到了。在组件里订阅了一下路由的 data,这个 data 是个 Observable 。

在 Post 模块的路由模块里面,设置了一下 posts/:id 这条路由的 resolve 属性,里面添加了一个 entity,这个 entity 的值是用 PostDetailResolveService 获取到的。

打开 PostDetailResolveService ,在这个服务的 resolve 方法里面,用了一下 PostService 服务上的 show 方法获取到了内容详情数据。

打开 PostService 服务,修改一下这个服务里的 show 这个方法,这里让它 return 的是用一下 this.http 的 get 方法,设置一下值的类型,可以是 Post。然后把服务接口地址交给这个方法,这个地址应该是 this.postsApi,斜线,再加上这个 show 方法的 id 参数的值。

选中这个 Post,按一下 command + . ,然后选择导入这个东西。

再回到 PostDetailResolveService,这个 resolve 方法,现在 return 的值应该是一个 Observable,值的类型是 Post。

预览

回到浏览器预览一下,打开内容列表里的一个项目,现在会显示这个内容项目的详情。 在 PostDetailsComponent 组件的视图文件里面,再添加一个图像,一个 img 标签,在上面绑定 src 属性,值是 entity 的 image,再绑定一个 alt 属性,值是 entity 的 title。

打开组件的样式表,设置一下 img 的样式,把它的 width 设置成 100% 。然后再回到浏览器预览一下,现在内容详情页面上就会出现一张照片。

来自   https://ninghao.net/video/7751#info


8)处理请求遇到的错误


用 HttpClient 请求服务端接口的时候可能会遇到两种类型错误,一种是服务端接口可能会返回错误的响应,比如状态码是 500,表示服务端应用本身出了问题,或者 404 的响应,表示没找到请求的资源。还有一种类型的错误就是可能因为网络问题无法正常请求服务端接口。

处理请求发生的错误,可以直接在订阅这个请求返回的 Observable 的时候,提供给它的 observer 里面添加一个 error 属性,然后设置一下怎么去处理发生的错误。

添加一个 observer ,值是个对象,里面添加一个 next,设置一下怎么样使用 Observable 上生产出来的数据。再添加一个 error,可以设置一下出现错误的时候要做的事情。

有个 error 参数,它的类型应该是 HttpErrorResponse ,方法要做的事情可以在控制台上输出这个 error 。

再把创建的这个 observer 交给 subscribe 方法。

预览

打开终端,可以停止运行之前我们创建的这个服务端应用。回到浏览器可以预览一下,刷新一下页面,因为请求的服务端应用已经停了,所以请求也就会遇到了错误。在浏览器的控制台,输出了这个 error 的值,它是一个 HttpErrorResponse ,里面有错误信息,名字,状态,地址等等。

来自   https://ninghao.net/video/7752#info

9)错误处理服务(catchError, throwError)


如果处理错误的逻辑比较复杂,不要把它们放在组件里,这件事可以交给服务去做。比如在这个 PostService 服务里面,添加一个处理请求发生的错误用的方法,名字可以是 handleError,接收一个 error 参数,值的类型是 HttpErrorResponse。

在这个方法里你可以检查这个 error,根据它里面的值去做出不同的反应。最终要让这个方法 return 一下执行 throwError 返回的 Observable,设置一下错误信息,Something went wrong.

这里用的 throwError 来自 rxjs。 下面用一下这个处理错误用的方法。

使用 HttpClient 的 get 方法请求内容列表接口,可以给它接上一个管道,用一个 pipe 方法,在这个 pipe 里面再安排一个 catchError 操作员,用它捕获到发生的错误,然后把 handleError 交给它。这样 catchError 捕获到发生的错误以后会交给 handleError 这个方法来处理。

预览

回到浏览器,现在请求内容列表接口出现了问题,我们安排的 catchError 操作员就会得到这个错误,把它交给 handleError 方法来处理,在这个方法里,又用了 throwError 扔出来一个错误,设置的错误信息是 Something went wrong。

在控制台上你会看到这条错误信息。

来自  https://ninghao.net/video/7753#info

10)重试(retry, retryWhen, delay, take)


请求接口出现错误的时候可以重试几次,在这个 pipe 里,再给它安排一个 retry 操作员,把要重试的次数交给这个操作员方法。这里用的这个 retry 来自 rxjs/operators。

回到浏览器预览一下,你会发现,这里有四次请求,可以打开 Network 选项卡,选择 XHR,再刷新一下页面,这里会出现四次对 posts 接口的请求,第一次请求出了问题以后,又重试了三次。

retryWhen

用 retryWhen 这个操作员可以控制重试行为,把 retry 换成 retryWhen,一个方法参数,这个方法里有个 errors 参数,这个 errors 是个 Observable。

给它接上一个 pipe ,里面可以用一个 delay 设置一下每次重试的延迟时间,设置成 3000,表示 3 秒钟时间,接着可以再用一个 take 操作员,给它的值设置成 3,这样就会每隔三秒钟时间,重试三次。

这里用的 delay 还有 take 这些东西都来自 rxjs/operators。

预览

回到浏览器预览一下,刷新一下页面,请求 posts 遇到了问题,开始重试,每次重试中间会相隔 3 秒钟的时候,并且会重试三次。

再试一下,刷新页面,然后回到终端,重新启动服务端应用。重试的时候网络恢复正常,页面上就会显示出请求回来的这次内容数据了。

来自   https://ninghao.net/video/7754#info

普通分类: