新新新手阅读 Angular 文件 - Get data from a server(1) - Day10

学习目标

本文章将会是阅读官方文件 Get data from a server 内容所做的笔记。
本章节会教如何透过 Angular 的 HTTP 功能,来取得、新增、编辑、删除有关英雄的资料。

加入 HTTP 服务

Angular 是透过 HTTPClient 这个功能来达到发出 HTTP 请求来跟远端服务器互动。

Step1.
我们要在 AppModule 中引用 HttpClientModule 模组。并在 AppModule 的 imports 加入这个模组。

--- app.module.ts ---
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  imports: [
    //...,
		HttpClientModule 
  ]
})

模仿与远端服务器取资料的情境

在官方文件中,提供了一个 In-memory Web API package 的模组,让我们可以使用 Angular 的 HTTPClient 模组来跟 In-memory Web API package 取资料,来模仿与远端服务器取资料的情境。

这部分就跟这官方文件教的安装 In-memory Web API package 的步骤,在你的专案中安装这个套件,并在安装完成之後,记得在 app.module.ts 中引入这个套件。

创出假的远端资料库资料

输入指令 ng generate service InMemoryData,会发现在专案资料夹中出现 in-memory-data.service.ts 这个档案,我们接下来就要在这个档案中加入英雄资料的资料库内容。

这边的内容就是按照官方文件所给的内容加入到 in-memory-data.service.ts 档案中就可以了,这边就先不赘述了。

加入 http 功能

接下来,我们就在 HeroService 加入 HTTPClient 的功能,就可以在元件里面透过它来发送 HTTP 请求罗。

Note:
有注意到吗! 在 HeroService 所属的模组 AppModule 我们先引入了 HttpClientModule ,接着,才在使用 http 请求的 HeroService 引入 HTTPClient ,才有办法使用 HTTP 请求。

--- hero.service.ts ---
import { HttpClient, HttpHeaders } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class HeroService {
  private heroesUrl = 'api/heroes';

  constructor (
    private http: HttpClient,
  ) {}
  
  /* 原本取得英雄资料的方法
  getHeroes(): Observable<HERO[]> {
     const heroes = of(HEROES);
     this.messageService.add('HeroService: fetched heroes');
     return heroes;
  }
  */
  
  getHeroes(): Observable<Hero[]> {
    return this.http.get<Hero[]>(this.heroesUrl)
  }
}

除了引入了 HttpClient 和 HttpHeaders。
也定义了目标资料库的路径 heroesUrl = 'api/heroes'
接着,将原本的 getHeroes 函式,改为用 http 的 get 方法从目标 url 中取回英雄资料。

HttpClient 方法会回传一种值

所有的 HttpClient 的方法都会回传属於某个 Observable 实例的内容。

一般来说 RxJS 中的 Observable 是具有可以回传好几个数值的特性,但是,来自 HttpClient 的 Observable 就只会传出一个值,并在传出这个值之後,就不会再传出任何值了。

错误处理

引入 catchError 和 pipe 模组,利用 pipe 将 catchError 模组的内容,接在某些取 API 回传资料的程序後面,用以做错误处理的对应。

--- hero.service.ts ---
import { catchError, map, tap } from 'rxjs/operators';

getHeroes(): Observable<Hero[]> {
  return this.http.get<Hero[]>(this.heroesUrl)
    .pipe(
      catchError(this.handleError<Hero[]>('getHeroes', []))
    );
}
private handleError<T>(operation = 'operation', result?: T) {
  return (error: any): Observable<T> => {

    // TODO: send the error to remote logging infrastructure
    console.error(error); // log to console instead

    // Let the app keep running by returning an empty result.
    return of(result as T);
  };
}

透过 id 取的英雄资料

定义目标路径为 api/heroes/id。前面的 baseUrl 我们再前面有定义过了,并将它设为变数 heroesUrl 的内容。後面的 id 就是要被获取详细资料的英雄的 id。

--- hero.service.ts ---
getHero(id: number): Observable<Hero> {
  const url = `${this.heroesUrl}/${id}`;
  return this.http.get<Hero>(url).pipe(
    catchError(this.handleError<Hero>(`getHero id=${id}`))
  );
}

这边要注意,这边的函式名称是 getHero 其中 Hero 是单数,而上面的是 getHeroes 其中的 Heroes 是复数,两者不相同喔,要注意一下~

Summary

这边做一个小总结,到这边我们知道了

  1. 引用 Angular 的 HttpClientModule 模组,就可以透过 http 来对远端的服务器做 CURD 的操作。
  2. 来自 httpclient.get 的 Observable 只会传出一个值。
  3. 在要使用 HTTP 请求功能的模组中要引入 HttpClient 这个模组。接着,就可以利用 this.HttpClient.get 这种语法来执行 GET 的请求。
  4. 我们可以引入 catchError 模组,并将它 pipe 在某些 API 操作後面,负责错误处理。

<<:  2021 — 找工作 (上)

>>:  Day 08 | 触发事件

[Day07] CH05:如果我有一座新冰箱——if/else 条件判断

昨天的练习题有做出来吗?是不是有遇到什麽问题呢? 第一个问题应该是两数相除完呈现整数,这时候我们需要...

【如何设计软件 ? 】领域驱动设计 | 4 层架构 + 3 类物件

有想法 x 也有做法 大纲 前人的专案 领域驱动设计 理论与分层结构 领域层的物件 专案架构实作 有...

xargs - Linux里好用的工具

xargs xargs原来意思是build and execute command lines fr...

Day10 - LinearLayout线性布局

目前Android Studio预设的布局是ConstraintLayout 它的效能比起其他布局还...

20. React Hooks 想改善的问题 ( + 简单实作 useState)

( 今天的文章要写React的相关问题,完全没有写过React的人,建议从中文官方文件开始练习。) ...