Angular - 删除



HttpClient delete() 方法

要删除服务器中的资源,可以使用 HTTP 动词 delete。delete 动词的目的是删除服务器中的特定资源。

Angular HttpClient 提供了一个方法 delete(),可以使用 delete HTTP 动词删除服务器中给定的资源。让我们在本节中学习 HttpClient delete() 方法。

delete() 方法的签名

delete() 方法的签名如下:

delete(<url as string>, <options as object>)
  • URL 表示要删除的服务器中资源的 URI。

  • options 表示要与资源 URL 一起发送的选项。

选项

可用的选项如下:

  • observe
  • responseType
  • headers
  • params
  • context
  • reportProgress
  • withCredentials
  • transferCache

observe

observe 用于指定在服务器通信期间要观察响应的哪一部分。根据 observe 选项,将返回整个响应或部分响应作为 Observable。可能的值为 body、events 和 response。

response 用于将 HTTP 请求的完整响应作为 Observable<HttpResponse<R>> 返回,其中 R 基于 requestType 选项(我们将在下一节中检查)和请求的数据类型 (Expense)。HttpResponse 类的目的是表示来自服务器的完整 HTTP 响应。

this.http.delete<Expense>(<url>, { 'observe': 'response', 'responseType' : 'json' })

这里,

  • json 是用于解释响应体的格式

  • Expense 是用于格式化响应体并返回 Observable<HttpResponse<Expense>> 的请求类型

events 用于返回响应流中触发的事件以及相应的响应体作为 Observable<HttpEvent>,其中 R 基于 requestType 选项和请求的数据类型 (Expense)。

this.http.delete<Expense>(<url>, { 'observe': 'events', 'responseType' : 'json' })

这里,

  • json 是用于解释响应体的格式

  • Expense 是用于格式化响应体并返回 Observable<HttpEvent<Expense>> 的请求类型

body 用于仅返回 HTTP 请求的响应体内容作为 Observable,其中 R 基于 requestType 选项和请求的数据类型 (Expense)。

this.http.delete<Expense>(<url>, { 'observe': 'body', 'responseType' : 'json' })

这里,

  • json 是用于解释响应体的格式

  • Expense 是用于格式化响应体并返回 Observable<Expense> 的请求类型

responseType

responseType 用于解释响应体。它可以有四个可能的值,如下所示:

  • arraybuffer
  • blob
  • text
  • json

让我们逐一了解这些选项

arraybuffer 用于将响应体解释为通用原始二进制数据缓冲区并返回 `Observable。它可用于流式传输音频/视频内容。

this.http.delete(<url>, { 'observe': 'body', 'responseType' : 'arraybuffer' } )

blob 用于将响应体解释为二进制格式并返回 Observable<blob>。它可用于下载大文件。

this.http.delete(<url>, { 'observe': 'body', 'responseType' : 'blob' })

text 用于将响应体解释为纯文本格式并返回 Observable<String>。它可用于表示基于文本的数据。

this.http.delete(<url>, { 'observe': 'body', 'responseType' : 'json' })

json 用于将响应体解释为 json 格式并返回 Observable<R>,其中 R 是请求的数据类型 (Expense)。它可用于以 json 格式表示结果。通过在方法中指定类型变量 (R) 可以进一步将其编码为任何类型,如下所示:

this.http.delete<Expense>(<url>, { 'observe': 'body', 'responseType' : 'json' })

根据 observe 和 responseType,Httpclient 将返回具有不同类型变量的 Observable。让我们检查 observe 和 responseType 的一些组合以更好地理解这个概念。

  • observe => body 和 responseType => json

    返回 Observable。R 表示类型变量。

  • observe => response 和 responseType => json

    返回 Observable<HttpResponse>。R 表示类型变量并编码响应体。

  • observe => events 和 responseType => json

    返回 Observable<HttpEvent>。R 表示类型变量并编码响应体。

  • observe => events 和 responseType => arraybuffer

    返回 Observable<HttpEvent>。响应体被编码为 ArrayBuffer。

  • observe => response 和 responseType => blob

    返回 Observable<HttpEvent>。响应体被编码为 ArrayBuffer。

  • observe => response 和 responseType => text

    返回 Observable<HttpResponse>。响应体被编码为 ArrayBuffer。

我们可以根据需要组合 observe 和 responseType 来创建更多组合。

headers

headers 用于指定 HTTP 标头。它可以包含标准 http 标头作为键/值对,也可以在 HttpHeaders 类中编码数据。一个作为键/值对的示例标头如下:

{ 'Content-type': 'application/json' }

它指定请求内容类型为 json。我们还可以使用 Angular 提供的 HttpHeaders 类来创建 http 标头。使用 HttpHeaders 的示例标头集如下:

// create header using `HttpHeaders`
const headers = new HttpHeaders()
   .set('content-type', 'application/json')
   .set('Access-Control-Allow-Origin', '*');

this.http.delete<Expense>(<url>, 
   { 'observe': 'body', 'responseType' : 'json', headers: headers })

params

params 用于以 application/x-www-form-urlencoded 格式表示序列化请求参数。它可以包含作为键/值对的参数,也可以在 HttpParams 类中编码数据。一个作为键/值对的示例参数如下:

{ 'name': 'john' }

它指定请求参数键为 name,其值为 john。我们还可以使用 Angular 提供的 HttpParams 类来创建参数。使用 HttpParams 的示例参数集如下:

// create parameters using `HttpParams`
const params = new HttpParams()
   .set('name', 'john')
   .set('age', 25)
   .set('active', true;

this.http.delete<Expense>(<url>, 
   { 'observe': 'body', 'responseType' : 'json', params: params })

context

context 用于以类型安全的方式发送任意值作为键/值对,并且没有键冲突。它用作拦截器的信息来源,充当客户端和服务器之间的中间件。Angular 提供了一个特殊的类 HttpContext 来编码上下文信息。一个示例上下文如下:

// create a key using HttpContextToken
export const IS_AUTH_ENABLED = new HttpContextToken<boolean>(() => false);

// set data for the context
let authContext = new HttpContext().set(IS_AUTH_ENABLED, true)

this.http.request<Expense>('GET', <url>, 
   { 'observe': 'body', 'responseType' : 'json', context: authContext })

这里,

  • HttpContextToken 用于创建键以及值类型。

  • IS_AUTH_ENABLED 是键,其类型为布尔值

reportProgress

reportProgress 用于指定是否将服务器发送回请求(通信)的进度。它可用于显示通过 Web API 上传大文件的进度。

this.http.delete<Expense>(<url>, 
   { 'observe': 'events', 'responseType' : 'json', reportProgress: true })

withCredentials

withCredentials 用于指定是否应将请求与传出凭据(cookie)一起发送。它接受布尔值。

this.http.delete<Expense>(<url>, 
   { 'observe': 'body', 'responseType' : 'json', withCredentials: true })

transferCache

transferCache 用于指定是否应缓存请求。它接受布尔值或 HttpTransferCacheOptions 值。HttpTransferCacheOptions 用于编码动态逻辑,以根据自定义过滤器函数过滤要缓存的请求并覆盖默认缓存行为。

this.http.delete<Expense>(<url>, 
   { 'observe': 'body', 'responseType' : 'json', transferCache: true })

工作示例

要完成 HTTP 客户端-服务器通信,我们需要设置一个 Web 应用程序,并且需要公开一组 Web API。可以从客户端请求 Web API。让我们创建一个示例服务器应用程序 Expense API App,为费用提供 CRUD REST API(主要是 DELETE 方法)。

步骤 1:转到您喜欢的 workspace,如下所示:

cd /go/to/your/favorite/workspace

步骤 2:创建一个新文件夹 expense-rest-api 并移动到该文件夹

mkdir expense-rest-api && cd expense-rest-api

步骤 3:使用 npm 命令提供的 init 子命令创建一个新应用程序,如下所示:

npm init

以上命令会询问一些问题,并使用默认答案回答所有问题。

步骤 4:安装 express 和 cors 包以创建基于节点的 Web 应用程序。

npm install express cors --save

步骤 5:安装 sqlite 包以将费用存储在基于 sqlite 的数据库中

npm install sqlite3 --save

步骤 6:创建一个新文件 sqlitedb.js 并添加以下代码以使用费用表和示例费用条目初始化数据库。费用表将用于存储费用项目

var sqlite3 = require('sqlite3').verbose()
const DBSOURCE = "expensedb.sqlite"

let db = new sqlite3.Database(DBSOURCE, (err) => {
   if (err) {
      console.error(err.message)
      throw err
   }else{
      console.log('Connected to the SQLite database.')
      db.run(`CREATE TABLE IF NOT EXISTS expense (
         id INTEGER PRIMARY KEY AUTOINCREMENT,
         item text, 
         amount real, 
         category text, 
         location text, 
         spendOn text, 
         createdOn text 
      )`,
         (err) => {
            if (err) {
               console.log(err);
            }else{
               var insert = 'INSERT INTO expense (item, amount, category, location, spendOn, createdOn) VALUES (?,?,?,?,?,?)'
         
               db.run(insert, ['Pizza', 10, 'Food', 'KFC', '2020-05-26 10:10', '2020-05-26 10:10'])
               db.run(insert, ['Pizza', 9, 'Food', 'Mcdonald', '2020-05-28 11:10', '2020-05-28 11:10'])
               db.run(insert, ['Pizza', 12, 'Food', 'Mcdonald', '2020-05-29 09:22', '2020-05-29 09:22'])
               db.run(insert, ['Pizza', 15, 'Food', 'KFC', '2020-06-06 16:18', '2020-06-06 16:18'])
               db.run(insert, ['Pizza', 14, 'Food', 'Mcdonald', '2020-06-01 18:14', '2020-05-01 18:14'])
            }
         }
      );  
   }
});

module.exports = db

步骤 7:打开 index.js 并更新以下代码,

var express = require("express")
var cors = require('cors')
var db = require("./sqlitedb.js")

var app = express()
app.use(cors());

var bodyParser = require("body-parser");
app.use(express.urlencoded({ extended: true }));
app.use(express.json());

var HTTP_PORT = 8000
app.listen(HTTP_PORT, () => {
   console.log("Server running on port %PORT%".replace("%PORT%", HTTP_PORT))
});

app.get("/", (req, res, next) => {
   res.json({ "message": "Ok" })
});

app.get("/api/expense", (req, res, next) => {
   var sql = "select * from expense"
   var params = []
   db.all(sql, params, (err, rows) => {
   if (err) {
      res.status(400).json({ "error": err.message });
      return;
   }
   res.json(rows)
   });
   
});

app.get("/api/expense/:id", (req, res, next) => {
   var sql = "select * from expense where id = ?"
   var params = [req.params.id]
   db.get(sql, params, (err, row) => {
   if (err) {
      res.status(400).json({ "error": err.message });
      return;
   }
   res.json(row)
   });
});

app.use(function (req, res) {
   res.status(404);
});

这里,代码将创建以下六个提到的 REST API 端点

  • / 端点返回 OK 消息以确保应用程序正常工作

  • /api/expense 端点返回数据库中所有可用的费用项目

  • /api/expense/:id 端点根据费用条目 ID 返回费用条目

  • /api/expense/:id 端点使用 delete 动词将根据费用条目 ID 删除费用条目

步骤 8:运行应用程序,如下所示:

node index.js

步骤 9:要测试应用程序并确保其正常工作,请打开浏览器并转到 https://127.0.0.1:8000/。如果应用程序正常工作,它应该返回以下消息。

{ 
   "message": "Ok" 
}

让我们创建一个有效的 Angular 示例,以使用 HttpClient 服务类删除服务器中现有的费用。

步骤 10:通过运行 ng new 命令创建一个新的 Angular 应用程序,如下所示:

ng new my-http-app

启用 Angular 路由和 CSS,如下所示:

? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS

步骤 11:通过在模块配置文件 (app.module.ts) 中导入 HttpClientModule 来启用应用程序中的 http 通信。

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

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { HttpClientModule } from '@angular/common/http';

@NgModule({
   declarations: [
      AppComponent
   ],
   imports: [
      BrowserModule,
      AppRoutingModule,
      HttpClientModule
   ],
   providers: [],
   bootstrap: [AppComponent]
})
export class AppModule { }

这里,

  • 从 @angular/common/http 模块导入 HttpClientModule。

  • 将 HttpClientModule 添加到 @NgModule 配置的 imports 部分。

步骤 12:创建一个新的接口 Expense 来表示我们的费用项目。

interface Expense {
   id?: Number,
   item: String,
   amount: Number,
   category: String,
   location: String,
   spendOn: Date
}

export default Expense;

这里,

  • id 设置为可选属性

步骤 13:创建新的组件 ListExpenses 以显示来自服务器的费用项目。

ng generate component ListExpenses

它将创建如下所示的组件:

CREATE src/app/list-expenses/list-expenses.component.css (0 bytes)
CREATE src/app/list-expenses/list-expenses.component.html (28 bytes)
CREATE src/app/list-expenses/list-expenses.component.spec.ts (602 bytes)
CREATE src/app/list-expenses/list-expenses.component.ts (229 bytes)
UPDATE src/app/app.module.ts (581 bytes)

步骤 14:将我们的新组件包含到 App 根组件的视图 app.component.html 中,如下所示:

<app-list-expenses></app-list-expenses>

<router-outlet></router-outlet>

步骤 15:通过构造函数将 HttpClient 注入到 ListExpenses 组件中,如下所示:

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
   selector: 'app-list-expenses',
   templateUrl: './list-expenses.component.html',
   styleUrls: ['./list-expenses.component.css']
})
export class ListExpensesComponent {

   constructor(private http: HttpClient) { }
}

步骤 16:实现 OnInit 生命周期钩子,以便在 ListExpenses 组件初始化后向服务器请求费用。

export class ListExpensesComponent implements OnInit{
   constructor(private http: HttpClient) { }   
   ngOnInit(): void {
   }
}

步骤 17:创建一个局部变量 expenses 来保存来自服务器的费用。

export class ListExpensesComponent implements OnInit{
   expenses: Expense[] = [];   
   constructor(private http: HttpClient) { }   
   ngOnInit(): void {   
   }
}

步骤18:创建一个本地变量 expense,用于保存服务器创建的新支出。

export class ListExpensesComponent implements OnInit{
   expenses: Expense[] = [];
   newexpense: Expense | null = null;   
   constructor(private http: HttpClient) { }   
   ngOnInit(): void {   
   }
}

步骤19:通过传递支出列表 URL 和选项,调用 this.http(HttpClient 实例)对象的 get 方法,从服务器获取支出对象。然后,将支出设置到我们的本地变量 expenses 中。

export class ListExpensesComponent implements OnInit {
   expenses: Expense[] = [];
   newexpense: Expense | null = null;   
   constructor(private http: HttpClient) { }   
   ngOnInit(): void {
   
      this.http.get<Expense[]>('https://127.0.0.1:8000/api/expense',
         {
            'observe': 'body',
            'responseType': 'json'
         })
         .subscribe( data => {
            this.expenses = data as Expense[]
            console.log(this.expenses)
         })
   
   }
}

这里,

  • 将 Expense[] 设置为服务器返回的对象的类型。服务器将在其主体中以 JSON 格式发送支出对象数组以及新的支出对象。

  • 订阅请求(this.http.get)对象。然后将订阅的数据解析为支出对象的数组,并将其设置为本地支出变量(this.expenses)。

步骤20:添加一个新的 delete 方法,并通过传递删除 URL 调用 this.http(HttpClient 实例)对象的 delete() 方法。

export class ListExpensesComponent implements OnInit {
   expenses: Expense[] = [];
   newexpense: Expense | null = null;
   
   constructor(private http: HttpClient) { }   
   delete(id? : Number) : void {
      if (id) {
         this.http.delete<Expense>('https://127.0.0.1:8000/api/expense/' + id,{
            'observe': 'body',
            'responseType': 'json'
         })
            .subscribe( data => {
               console.log(data)
                  this.http.get<Expense[]>('https://127.0.0.1:8000/api/expense',{
                     'observe': 'body',
                     'responseType': 'json'
                  })
                  .subscribe( data => {
                     this.expenses = data as Expense[]
                     console.log(this.expenses)
                  })
            });
      }
   }   
   ngOnInit(): void {
   
      this.http.get<Expense[]>('https://127.0.0.1:8000/api/expense',{
         'observe': 'body',
         'responseType': 'json'
      })
      .subscribe( data => {
         this.expenses = data as Expense[]
         console.log(this.expenses)
      })
   
   }
}

步骤21:接下来,获取支出列表对象,并在我们的组件模板页面(list-expenses.component.html)中渲染它。此外,为每个支出添加锚标记,并通过传递相应的支出 ID 设置删除方法。

<div><h3>Expenses</h3></div>
<ul>
   <li *ngFor="let expense of expenses">
      {{expense.item}} @ {{expense.location}} for {{expense.amount}} USD on {{expense.spendOn | date:'shortDate' }} <a href="delete(expense.id)">delete</a>
   </li>
</ul>

这里,

  • 当用户点击删除链接时,它将调用删除支出端点,并从服务器删除支出。

步骤22:ListExpensesComponent 的完整代码如下所示:

import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpRequest, HttpResponse, HttpEvent, HttpParams } from '@angular/common/http';
import Expense from '../Expense';

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

   expenses: Expense[] = [];
   newexpense: Expense | null = null;
   
   constructor(private http: HttpClient) { }
   
   ngOnInit(): void {
   
   var spend_date = new Date();
   spend_date.setDate(spend_date.getDate() - 1);
   this.newexpense = {
      'item': 'new item ' + Math.floor(Math.random() * 10),
      'amount': Math.floor(Math.random() * 100),
      'category': 'Food',
      'location': 'KFC',
      'spendOn': spend_date
   }
   
   this.http.delete<Expense>('https://127.0.0.1:8000/api/expense/1',
      this.newexpense,{
         'observe': 'body',
         'responseType': 'json'
      })
      .subscribe( data => {
         this.newexpense = data as Expense;
         console.log(data)
      });   
      this.http.get<Expense[]>('https://127.0.0.1:8000/api/expense',{
         'observe': 'body',
         'responseType': 'json'
      })
      .subscribe( data => {
         this.expenses = data as Expense[]
         console.log(this.expenses)
      })
   
   }
}

步骤23:最后,使用以下命令运行应用程序:

ng serve

步骤24:打开浏览器并导航到 https://127.0.0.1:4200/ URL,并检查输出。

这里,输出显示我们的支出作为一个项目列表,除了项目 1。

结论

Angular 提供了一种简单的方法,可以通过 HttpClient 对象将数据发送到服务器。delete() 是一个用于将数据发送到服务器的特定方法。我们将在后续章节中学习更多 http 方法,以针对其他 http 动词。

广告