实现[Angular] HTTP客户端(REST客户端)

首先

让我们来看一下如何通过Angular与后端进行通信。
我们将使用Http HttpClient服务,并确认通过REST API实现的方法。

最新的資訊

2021年8月14日

補足-3 として、レスポンスにヘッダ情報を含める設定について追記しました

2021年1月4日

    記事内で扱ったコードを Angular v11.0.5 で確認しました

2019年3月22日 (2019 3 yuè 22 rì)

    Angular 7.2.2 の現在、Headers が非推奨となっているため、REST-API のヘッダ情報を HttpHeaders を使用するよう修正しました

2018年5月13日

    • Angular 5.0.0 で @angular/http が非推奨( 出典:Version 5.0.0 of Angular Now Available )となったため、Httpクライアントモジュールを @angular/common/http に変更しました

 

    「登録」「更新」「削除」 の動作検証を行えるよう UI を変更しました

工作环境

后端

Node.js和npm的版本要与前端一致。

環境バージョン備考expressv4.14.1package.json の記載から

前端

環境バージョン備考Angular CLIv6.1.3 v11.0.5$ ng --versionAngularv6.1.2 v11.0.5同上TypeScriptv4.0.2同上Node.jsv9.4.0 v12.18.3$ node --versionnpmv6.1.0 v6.14.6$ npm --version
ng版本的结果
$ ng版本_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | ‘_ \ / _` | | | | |/ _` | ‘__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/

Angular CLI: 11.0.5
Node: 12.18.3
操作系统: darwin x64

Angular版本: 11.0.5
… 动画, CLI, 公共模块, 编译器, 编译器CLI, 核心, 表单
… 平台浏览器, 动态平台浏览器, 路由器
使用的Workspace: 是

包 版本
———————————————————
@angular-devkit/architect 0.1100.5
@angular-devkit/build-angular 0.1100.5
@angular-devkit/core 11.0.5
@angular-devkit/schematics 11.0.5
@schematics/angular 11.0.5
@schematics/update 0.1100.5
rxjs 6.6.0
typescript 4.0.2

形成

    • バックエンド

 

    • Express( http://localhost:3000 )

 

    • フロンドエンド

 

    Angular( http://localhost:4200 )

后端

本節将实现一个简单的服务器,用于接收使用Express发出的请求。虽然本文的目的是通过Angular实现Http客户端,但为了实现这一目的,也需要一个与之配合的后端。关于Express的开发环境搭建,可以参考这篇文章(链接)。

var express = require('express');
var router = express.Router();

var strage = {
  id: 0,
  message: 'デフォルトメッセージ'
};

const strages = [strage];

/**
 * HTTP の GET メソッドを待ち受けてステータスコードと文字列, メッセージリストを返す
 * レスポンスは下記のJSONフォーマットで返却する
 * {
 *   status: 200,
 *   response: 'メッセージリストを返却',
 *   messages: {{メッセージリスト}}
 * }
 * といった JSON が返却される
 */
router.get('/message/get', function(req, res, next) {
  res.status(200);
  res.json({
    status: 200,
    response: 'メッセージリストを返却',
    messages: strages
  });
});

module.exports = router;

关于实现没有特别的要点,就按照代码中的注释来做。
虽然重复了源代码的注释,但只是简单地在路由器上注册了一个等待接收 HTTP 的 GET 方法的处理程序。

{
  status: 200,
  response: 'メッセージリストを返却',
  messages: {{メッセージリスト}}
}

回复如下。

前端

按照开头所述,这里我们使用Angular标准提供的Http HttpClient服务来实现HTTP客户端。
在以下的部分,我们将探讨如何实现向后端发出GET请求并显示从后端获取的字符串。

为了使用 HttpClient 服务,导入 HttpClientModule。

为了使用 Http HttpClient 服务,需要在 app.module.ts 中导入 HttpModule HttpClientModule。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

// HTTP クライアントのための import ( 下記は Angular 5.0.0 で非推奨となった )
//import { HttpModule } from '@angular/http';

// HTTP クライアントのための import ( Angular 5.0.0 以降はこちらを使う )
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';

// HTTP クライアントとしてのコンポーネント
import { HttpClientComponent } from './http-client/http-client.component';

// バックエンドとの通信を実際に担当するサービス
import { HttpClientService } from './service/http-client.service';

@NgModule({
  declarations: [
    AppComponent,
    HttpClientComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    // モジュールを利用を宣言する
    // 下記は Angular 5.0.0 で非推奨となった
    //HttpModule
    // Angular 5.0.0 以降はこちらを使う
    HttpClientModule
  ],
  providers: [
    // 自作サービスをアプリ全体で DI するために登録する
    HttpClientService
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

在app.module.ts中,您需要查看以下两个方面。

    在中国人的日常生活中,只需要一种选择:“HttpModule HttpClientModule”的导入声明。

通过这两点来准备在整个应用程序中使用 Http 服务。

负责与后端通信的服务(例如GET请求)

实现一个负责与后端进行实际通信的服务的角色。实现内容大致如下:

Http HttpClient サービスの import

バックエンドから提供されている REST-API の実行

以下是GET请求的示例代码。

import { Injectable } from '@angular/core';

// REST クライアント実装ののためのサービスを import ( 下記は Angular 5.0.0 で非推奨となった )
//import { Http } from '@angular/http';

// REST クライアント実装ののためのサービスを import ( Angular 5.0.0 以降はこちらを使う )
import { HttpClient, HttpHeaders } from '@angular/common/http';

@Injectable()
export class HttpClientService {

  // 下記のコードは非推奨
  /**
   * リクエストヘッダを定義
   *
   * @private
   * @memberof HttpClientService
   */
  //private headers: any = new Headers({'Content-Type': 'application/json'});

  // `Headers` の代わりに `HttpHeaders` を利用する
  // またコメントにあるとおり、 `Authorization` を設定できるように `httpOptions` としてオブジェクトでラップしている
  // 参考
  // https://angular.jp/guide/http#%E3%83%98%E3%83%83%E3%83%80%E3%83%BC%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B
  /**
   * Http クライアントを実行する際のヘッダオプション
   * @private
   * @type {*}
   * @memberof HttpClientService
   * @description
   * 認証トークンを使用するために `httpOptions` としてオブジェクトを用意した。
   */
  private httpOptions: any = {
    // ヘッダ情報
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    }),
    //
    // レスポンスにヘッダ情報を入れるための設定
    // https://angular.io/guide/http#reading-the-full-response
    //
    observe: 'response',  // ⇐ これを追加
    //
    // DELETE 実行時に `body` が必要になるケースがあるのでプロパティとして用意しておく
    // ( ここで用意しなくても追加できるけど... )
    body: null
  };

  /**
   * RST-API 実行時に指定する URL
   *
   * バックエンドは Express で実装し、ポート番号「3000」で待ち受けているため、
   * そのまま指定すると CORS でエラーになる
   * それを回避するため、ここではフロントエンドのポート番号「4200」を指定し、
   * Angular CLI のリバースプロキシを利用してバックエンドとの通信を実現する
   *
   * @private
   * @memberof HttpClientService
   */
  private host: string = 'http://localhost:4200/app';

  /**
   * コンストラクタ. HttpClientService のインスタンスを生成する
   *
   * @param {Http} http Httpサービスを DI する
   * @memberof HttpClientService
   */
  constructor(private http: HttpClient) {
    // `Authorization` に `Bearer トークン` をセットする
    this.setAuthorization('my-auth-token');
  }

  /**
   * HTTP GET メソッドを実行する
   * (toPromise.then((res) =>{}) を利用する場合のコード)
   *
   * @returns {Promise<any[]>}
   * @memberof HttpClientService
   */
  public get(): Promise<any[]> {
    return this.http.get(this.host + '/message/get', this.httpOptions)
    .toPromise()
    .then((res) => {
      // response の型は any ではなく class で型を定義した方が良いが
      // ここでは簡便さから any としておく

      // @angular/http では json() でパースする必要があったが、 @angular/common/http では不要となった
      //const response: any = res.json();
      const response: any = res;
      return response;
    })
    .catch(this.errorHandler);
  }

  /**
   * REST-API 実行時のエラーハンドラ
   * (toPromise.then((res) =>{}) を利用する場合のコード)
   *
   * @private
   * @param {any} err エラー情報
   * @memberof HttpClientService
   */
  private errorHandler(err) {
    console.log('Error occured.', err);
    return Promise.reject(err.message || err);
  }

  /**
   * Authorizatino に認証トークンを設定しする
   *
   * @param {string} token 認証トークン
   * @returns {void}
   * @memberof HttpClientService
   * @description
   * トークンを動的に設定できるようメソッド化している
   * Bearer トークンをヘッダに設定したい場合はこのメソッドを利用する
   */
  public setAuthorization(token: string = ''): void {
    if (!token) {
      return;
    }
    const bearerToken: string = `Bearer ${token}`;
    this.httpOptions.headers = this.httpOptions.headers.set('Authorization', bearerToken);
  }
}

关于代码附加说明要写。

    1. 在RST-API执行时指定的URL。

 

    1. 由于前端和后端的端口号不同,因此会出现由CORS引起的错误。

 

    1. 如下所述,在本文中我们使用Angular CLI的反向代理来避免这个问题,并在此处指定反向代理的URL为http://localhost:4200/app。

执行RESTR-API
通过执行Http HttpClient服务的get方法,执行后端提供的REST-API。
注意,此时使用箭头函数中的toPromise.then((res) => {})来接收响应。
这是一种通过toPromise()来异步接收执行REST-API,并在接收到响应后通过then((res) => {})进行处理的流程。
此外,通过toPromise()将本来是Observable对象的http.get()的返回值强制转换为Promise对象,从而使后续处理可以在Promise对象的方法中进行。
接下来是如何处理返回的响应。
由于后端以JSON格式返回响应,因此在这里使用json()将响应恢复为JSON格式。
在@angular/http中需要使用json()进行解析,但在@angular/common/http中则不需要,所以在这里直接设置返回的响应。

设置授权
为了能够动态设置Bearer令牌,我们将设置令牌的过程封装为setAuthorization()方法。
尽管本文在构造函数中执行这个方法,但不一定非要在构造函数中执行。可以在获得令牌的时候设置,或者在其他合适的时机设置。请根据需求选择合适的时机。

补充说明
尽管在注释中提到,对于从后端返回的数据,最好是准备一个类或接口来存储返回的值,而不是使用any进行处理。但在本文中,由于是示例代码,所以使用any来处理。

使用创建的服务的组件

使用已创建的 HttpClientService 实现一个从后端获取信息的组件。

import { Component, OnInit } from '@angular/core';
import { HttpClientService } from '../service/http-client.service';

@Component({
  selector: 'app-http-client',
  templateUrl: './http-client.component.html',
  styleUrls: ['./http-client.component.css']
})
export class HttpClientComponent implements OnInit {

  /**
   * バックエンドから返却されたレスポンスをセットするプロパティ
   *
   * 型は any ではなく class で型を定義した方が良いが
   * ここでは簡便さから any としておく
   *
   * @private
   * @type {string}
   * @memberof HttpClientComponent
   */
  public param: any = {};

  /**
   * バックエンドから返却されたたメッセージをセットするプロパティ
   *
   * @type {*}
   * @memberof HttpClientComponent
   */
  public messageInfo: any = {
    id: null,
    message: null
  };

  /**
   * バックエンドから返却されたたメッセージを保持するリストプロパティ
   *
   * @type {*}
   * @memberof HttpClientComponent
   */
  public messageInfoList: any = [this.messageInfo];

  /**
   * メッセージ登録回数
   *
   * @private
   * @type {number}
   * @memberof HttpClientComponent
   */
  public messageId: number = 1;

  /**
   * 入力メッセージ
   *
   * @type {string}
   * @memberof HttpClientComponent
   */
  public message: string = '';

  /**
   * コンストラクタ. HttpClientComponent のインスタンスを生成する
   * 自作した HttpClientService を DI する
   *
   * @param {HttpClientService} httpClientService HTTP通信を担当するサービス
   * @memberof HttpClientComponent
   */
  constructor(private httpClientService: HttpClientService) { }

  /**
   * ライフサイクルメソッド。コンポーネントの初期化で使用する
   * 今回はコンポーネントの初期化時にバックエンドから情報を取得してビューに表示する
   *
   * @memberof HttpClientComponent
   */
  ngOnInit() {
    // ------
    // toPromise.then((res) =>{}) を利用する場合のコード
    // ------
    this.httpClientService.get()
    .then(
      (response: any) => {
        this.param = response.body;
        this.messageInfoList = this.param.messages;
      }
    )
    .catch(
      (error) => console.log(error)
    );
  }
}

重点在于

ngOnInit() で HttpClientService の get() メソッドを実行している

在这些地方,它正在等待then()函数返回的处理结果并处理从后端返回的响应。

只需要一种选项:以下是返回的响应内容,response.body 中设置了后端返回的下一个 JSON 对象。

params = {
    status: 200,
    response: 'メッセージリストを返却',
    messages: [
      {
        id: 0,
        message: 'デフォルトメッセージ'
      }
    ]
  }
]

为了使用 *ngFor 在ビュー( http-client.html )上显示消息列表, 将返回的响应设置为 this.messageInfoList。

<!-- 片方向データバインドでバックエンドから取得した情報を表示する -->
<table class="table">
  <caption>バックエンドから取得したメッセージリスト</caption>
  <tr>
    <th id="th-id">ID</th>
    <th id="th-message">メッセージ</th>
  </tr>
  <!--インデックス番号(index)に変数iでアクセスできるように-->
  <tr *ngFor="let messageInfo of messageInfoList; index as i">
    <td>{{messageInfo.id}}</td>
    <td>{{messageInfo.message}}</td>
  </tr>
</table>

<form #formCheck="ngForm" class="formCheck">
  <input type="text" id="form-id" class="input-text" name="message-id" [(ngModel)]="messageId">
  <input type="text" id="form-message" class="input-text" name="message" [(ngModel)]="message">
</form>

<input type="button" id="register" value="登録" (click)="onClickRegister($event)">
<input type="button" id="update" value="更新" (click)="onClickUpdate($event)">
<input type="button" id="delete" value="削除" (click)="onClickDelete($event)">

为了显示消息列表,视图处理是使用*ngFor从先前设置的messageInfoList类中提取一个个元素,然后引用id和message属性。

なお、タグ以降のブロックは、メッセージの「登録」、「更新」、「削除」を行うためのインターフェースの一部分です。「登録」、「更新」、「削除」の処理については、後述の補足-2で実装例を説明していますので、参考にしてください。

使用Angular CLI进行反向代理设置

首先要重申的是,本次内容的结构如下:

    • フロントエンドが Angular でポート番号:4200 で起動する

 

    バックエンドが Express でポート番号:3000 で起動する

在这种情况下,由于两者的端口号不同,所以即使从前端向后端发送请求,也会在CORS中出现错误。
为了避免这个问题,可以使用Angular CLI进行反向代理的设置。
(关于反向代理的设置,请参考这篇文章。仅供参考。)

以下为设定的内容。

    リバースプロキシ設定ファイル(proxy.conf.json)
{
  // localhost:4200/app を localhost:3000 にフォワード
  "/app": {
    "target": "http://localhost:3000",
    "pathRewrite": {"^/app": ""}
  }
}
    リバースプロキシ有りで起動するためのスクリプト
  // 省略
  "scripts": {
    // 省略
    // リバースプロキシ設定ファイルを読み込ませて起動する
    "start": "ng serve --proxy-config proxy.conf.json",
    // 省略
  },
  // 省略

设定了反向代理后,前端和后端之间的连接将会如下图所示。

    リバースプロキシ後のフロントエンド⇔バックエンド間
 フロントエンド ------> Angular CLI によるリバースプロキシ ------> バックエンド
(locahost:4200)                                        (localhost:3000)

当重新检查前面提到的 HttpClientService 和后端的 GET 方法时,在这里。

    フロントエンド
  // 省略
  private host: string = 'http://localhost:4200/app';

  // 省略

  /**
   * HTTP GET メソッドを実行する
   * (toPromise.then((res) =>{}) を利用する場合のコード)
   *
   * @returns {Promise<any[]>}
   * @memberof HttpClientService
   */
  public get(): Promise<any[]> {
    return this.http.get(this.host + '/message/get', this.httpOptions)
    .toPromise()
    .then((res) => {
      // response の型は any ではなく class で型を定義した方が良いが
      // ここでは簡便さから any としておく
      const response: any = res;
      return response;
    })
    .catch(this.errorHandler);
  }
    バックエンド
/**
 * HTTP の GET メソッドを待ち受けてステータスコードと文字列, メッセージリストを返す
 * レスポンスは下記のJSONフォーマットで返却する
 * {
 *   status: 200,
 *   response: 'メッセージリストを返却',
 *   messages: {{メッセージリスト}}
 * }
 * といった JSON が返却される
 */
router.get('/message/get', function(req, res, next) {
  res.status(200);
  res.json({
    status: 200,
    response: 'メッセージリストを返却',
    messages: strages
  });
});

已经实施。

总结前述内容,包括反向代理的设置、前端实现和后端实现所意图的内容,则可以如下表达:

将之前提到的反向代理的设置、前端实现和后端实现的目标进行综述,可简洁概括如下:

    1. 反向代理的设置将 localhost:4200/app 转发到 localhost:3000

 

    1. 后端在 localhost:3000/get 上等待请求

 

    1. 前端在 localhost:4200/app/get 上发出请求

 

    1. 通过反向代理的设置,上述请求被转发到 localhost:3000/get

 

    后端能够成功接收请求

成为如此。

当以前的参考文章中所提到的,当使用反向代理启动Angular时,请确保已设置好反向代理。

$ npm start

需要注意的是,虽然使用ng serve命令可以启动应用程序,但是由于存在反向代理,应用程序并未正确启动,因此无法按预期工作。

运行结果

请使用以下命令启动后端和前端。

$ npm start
$ npm start

一起启动后,从浏览器中查看执行结果。

http-client-get-result.png

我确认看到了从后端返回的值,即“默认消息”被显示出来。

填充-1

在这篇文章中提到了使用 HttpClientService 的 get() 方法并示范了使用 toPromise.then() 的例子,但也可以选择使用 subscribe() 作为替代方法。

在这种情况下,相应的每个代码将被实现如下。

将toPromise().then()替换为subscribe()。

    サービス
  /**
   * HTTP GET メソッドを実行する
   * (subscribe((res) =>{}) を利用する場合のコード)
   *
   * @param {*} callback HTTP GET の実行結果を受け取って処理するためのコールバック処理
   * @memberof HttpClientService
   */
  public get(callback: any) {
    this.http.get(this.host + '/message/get', this.httpOptions)
    .subscribe(
      (res) => {
        const response: any = res;
        callback(response);
      },
      (error) => {
        // subscribe の実装のときに this.errorHandler でエラー処理を
        // 行うと Uncaught (in promise) が発生するので、
        // ここではコンソールにログを出すだけにする
        console.log(error);
      }
    );
  }
如果使用HttpClientModule中的subscribe时,本文中的附加信息也提到了相关操作。如果方便的话,请参考一下。
    コンポーネント
  /**
   * ライフサイクルメソッド。コンポーネントの初期化で使用する
   * 今回はコンポーネントの初期化時にバックエンドから情報を取得してビューに表示する
   *
   * @memberof HttpClientComponent
   */
  ngOnInit() {
    // ------
    // subscribe((res) =>{}) を利用する場合のコード
    // ------
    // HTTP GET の実行結果を受け取るためのコールバックを引数に、 get() を呼び出す
    this.httpClientService.get((response: any) => {
      this.param = response.body;
      this.messageInfoList = this.param.messages;
    });
  }

填補-2

以下是POST、PUT和DELETE的示例。这些示例涉及对存储在内存中的消息信息的处理,但仅供您了解处理方式。

虽然在后端可能会返回错误,但前端只需将该错误输出为日志,使用 console.log(error),不进行其他处理。

邮寄

后端

/**
 * HTTP の POST メソッドを待ち受けてメッセージを登録する
 * 成功時、ステータスコードと文字列、登録後のメッセージリストを返す
 *
 * レスポンスは下記のJSONフォーマットで返却する
 * {
 *   status: 200,
 *   response: 'メッセージを登録',
 *   messages: {{メッセージリスト}}
 * }
 * といった JSON が返却される
 */
router.post('/message/post', function(req, res, next) {
  if (!req.body.id || req.body.id === '') {
    res.status(400);
    res.json({status: 400, response: 'IDが指定されていない'})
    return;
  }

  for (var i = 0; i < strages.length; i++) {
    if (req.body.id === strages[i].id) {
      res.status(409);
      res.json({
        status: 409,
        response: 'IDが重複',
        messages: req.body
      })
      return;
    }
  }

  const localStorage = {
    id: req.body.id,
    message: req.body.message
  };
  strages.push(localStorage);

  res.status(200);
  res.json({
    status: 200,
    response: 'メッセージを登録',
    messages: strages
  })
});

前端

    サービス
  /**
   * メッセージ登録
   *
   * @param {*} body リクエストボディ
   * @returns {Promise<any[]>} バックエンドからのレスポンス
   * @memberof HttpClientService
   */
  public register(body: any): Promise<any[]> {
    return this.http.post(this.host + '/message/post', body, this.httpOptions)
    .toPromise()
    .then((res) => {
      const response: any = res;
      return response;
    })
    .catch(this.errorHandler);
  }
    コンポーネント
  /**
   * メッセージ登録
   *
   * @private
   * @memberof HttpClientComponent
   */
  private doRegister() {
    const body: any = {
      id: this.messageId,
      message: this.message
    };
    this.httpClientService.register(body)
    .then(
      (response: any) => {
        this.param = response.body;
        this.messageInfoList = this.param.messages;
      }
    )
    .catch(
      (error) => console.log(error)
    );
  }

把东西放置

后端

/**
 * HTTP の PUT メソッドを待ち受けてメッセージを更新する
 * 成功時、ステータスコードと文字列、 更新後のメッセージリストを返す
 *
 * レスポンスは下記のJSONフォーマットで返却する
 * {
 *   status: 200,
 *   response: 'メッセージを更新',
 *   messages: {{メッセージリスト}}
 * }
 * といった JSON が返却される
 */
router.put('/message/put', function(req, res, next) {
  if (!req.body.id || req.body.id === '') {
    res.status(400);
    res.json({
      status: 400,
      response: 'IDが指定されていない',
      message: req.body
    })
    return;
  }

  for (var i = 0; i < strages.length; i++) {
    if (req.body.id === strages[i].id) {
      strages[i].message = req.body.message;
      res.status(200);
      res.json({
        status: 200,
        response: 'メッセージを更新',
        messages: strages
      })
      return;
    }
  }

  res.status(404);
  res.json({
    status: 404,
    response: '対象のメッセージが存在しない',
    messages: req.body
  })
});

前端

    サービス
  /**
   * メッセージ更新
   *
   * @param {*} body リクエストボディ
   * @returns {Promise<any[]>} バックエンドからのレスポンス
   * @memberof HttpClientService
   */
  public update(body: any): Promise<any[]> {
    return this.http.put(this.host + '/message/put', body, this.httpOptions)
    .toPromise()
    .then((res) => {
      const response: any = res;
      return response;
    })
    .catch(this.errorHandler);
  }
    コンポーネント
  /**
   * メッセージ更新
   *
   * @private
   * @memberof HttpClientComponent
   */
  private doUpdate() {
    const body: any = {
      id: this.messageId,
      message: this.message
    };
    this.httpClientService.update(body)
    .then(
      (response: any) => {
        this.param = response.body;
        this.messageInfoList = this.param.messages;
      }
    )
    .catch(
      (error) => console.log(error)
    );
  }

删除

后端 (Chinese translation for “backend”)

/**
 * HTTP の DELETE メソッドを待ち受けてメッセージを削除する
 * 成功時、ステータスコードと文字列、 削除後のメッセージリストを返す
 *
 * レスポンスは下記のJSONフォーマットで返却する
 * {
 *   status: 200,
 *   response: 'メッセージを削除',
 *   messages: {{メッセージリスト}}
 * }
 * といった JSON が返却される
 */
router.delete('/message/delete', function(req, res, next) {
  if (!req.body.id || req.body.id === '') {
    res.status(400);
    res.json({
      status: 400,
      response: 'IDが指定されていない',
      message: req.body
    })
    return;
  }

  for (var i = 0; i < strages.length; i++) {
    if (req.body.id === strages[i].id) {
      strages.splice(i, 1);
      res.status(200);
      res.json({
        status: 200,
        response: 'メッセージを削除',
        messages: strages
      })
      return;
    }
  }

  res.status(404);
  res.json({
    status: 404,
    response: '対象のメッセージが存在しない',
    messages: req.body
  })
});

前端

DELETE については次の点に注意

Http サービスの delete メソッドでは body を引数にセットできない
DELETE 時に body をセットしたい場合、例に示したように Header Option に含める 必要がある

サービス

  /**
   * メッセージ削除
   *
   * @param {*} body リクエストボディ
   * @returns {Promise<any[]>} バックエンドからのレスポンス
   * @memberof HttpClientService
   */
  public delete(body: any): Promise<any[]> {
    this.httpOptions.body = body;
    return this.http.delete(this.host + '/message/delete', this.httpOptions)
    .toPromise()
    .then((res) => {
      const response: any = res;
      return response;
    })
    .catch(this.errorHandler);
  }
    コンポーネント
  /**
   * メッセージ削除
   *
   * @private
   * @memberof HttpClientComponent
   */
  private doDelete() {
    const body: any = {
      id: this.messageId
    };
    this.httpClientService.delete(body)
    .then(
      (response: any) => {
        this.param = response.body;
        this.messageInfoList = this.param.messages;
      }
    )
    .catch(
      (error) => console.log(error)
    );
  }

执行 POST、PUT、DELETE 的结果.

邮递

http-client-post-result.png

放置

http-client-put-result.png

删除

http-client-delete-result.png

3个补充

要在响应中包含头信息,应该怎么做?

在执行HttpClient的每个方法时,添加 observe: ‘response’ 作为选项。
就本文的代码来说,下面的部分就是。

  private httpOptions: any = {
    // ヘッダ情報
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    }),
    //
    // レスポンスにヘッダ情報を入れるための設定
    // https://angular.io/guide/http#reading-the-full-response
    //
    observe: 'response',  // ⇐ これを追加
    //
    // DELETE 実行時に `body` が必要になるケースがあるのでプロパティとして用意しておく
    // ( ここで用意しなくても追加できるけど... )
    body: null
  };

设定如上时,响应内容为什么?

获取响应

[get] response:
{
    "headers":{
       "normalizedNames":{},
       "lazyUpdate":null
    },
    "status":200,
    "statusText":"OK",
    "url":"http://localhost:4200/app/get",
    "ok":true,
    "type":4,
    "body":{
        "status":200,
        "response":"メッセージリストを返却",
        "messages":[
            {
                "id":0,
                "message":"デフォルトメッセージ"
            }
        ]
    }
}

讨论帖的回复

[post] response: {
    "headers":{
        "normalizedNames":{},
        "lazyUpdate":null
    },
    "status":200,
    "statusText":"OK",
    "url":"http://localhost:4200/app/post",
    "ok":true,
    "type":4,
    "body":{
        "status":200,
        "response":"メッセージを登録",
        "messages":[
            {
                "id":0,
                "message":"デフォルトメッセージ"
            },
            {
                "id":1,
                "message":"hogehoge"
            }
        ]
    }
}

将”put”的响应解释。

[put] response: {
    "headers":{
        "normalizedNames":{},
        "lazyUpdate":null
    },
    "status":200,
    "statusText":"OK",
    "url":"http://localhost:4200/app/put",
    "ok":true,
    "type":4,
    "body":{
        "status":200,
        "response":"メッセージを更新",
        "messages":[
            {
                "id":0,
                "message":"デフォルトメッセージ"
            },
            {
                "id":1,
                "message":"hogehogehogehoge"
            }
        ]
    }
}

删除响应

[delete] response: {
    "headers":{
        "normalizedNames":{},
        "lazyUpdate":null
    },
    "status":200,
    "statusText":"OK",
    "url":"http://localhost:4200/app/delete",
    "ok":true,
    "type":4,
    "body":{
        "status":200,
        "response":"メッセージを削除",
        "messages":[
            {
                "id":0,"message":"デフォルトメッセージ"
            }
        ]
    }
}

源代码

請參考以下連結,其中包含了本次文章所使用的程式碼進行的操作驗證。

    • フロントエンド

 

    バックエンド

请参考

    • Version 5.0.0 of Angular Now Available

 

    • Angular 5.0.0がリリースされました( 上記の日本語訳 )

 

    • HttpClient – 公式の日本語ドキュメント

 

    Communicating with backend services using HTTP > Reading the full response
广告
将在 10 秒后关闭
bannerAds