- Angular 教程
- Angular - 首页
- Angular - 概述
- Angular - 特性
- Angular - 优点与缺点
- Angular 基础
- Angular - 环境搭建
- Angular - 第一个应用
- Angular - MVC 架构
- Angular 组件
- Angular - 组件
- Angular - 组件生命周期
- Angular - 视图封装
- Angular - 组件交互
- Angular - 组件样式
- Angular - 嵌套组件
- Angular - 内容投影
- Angular - 动态组件
- Angular - 元素
- Angular 模板
- Angular - 模板
- Angular - 文本插值
- Angular - 模板语句
- Angular - 模板中的变量
- Angular - SVG 作为模板
- Angular 数据绑定
- Angular - 数据绑定及其类型
- Angular - 数据绑定
- Angular - 事件绑定
- Angular - 属性绑定
- Angular - 属性绑定
- Angular - 类和样式绑定
- Angular 指令
- Angular - 指令
- Angular - 内置指令
- Angular 管道
- Angular - 管道
- Angular - 使用管道转换数据
- Angular 依赖注入
- Angular - 依赖注入
- Angular HTTP 客户端编程
- Angular - 服务
- Angular - HTTP 客户端
- Angular - 请求
- Angular - 响应
- Angular - GET 请求
- Angular - PUT 请求
- Angular - DELETE 请求
- Angular - JSON-P
- Angular - 使用 HTTP 进行 CRUD 操作
- Angular 路由
- Angular - 路由
- Angular - 导航
- Angular - Angular Material
- Angular 动画
- Angular - 动画
- Angular 表单
- Angular - 表单
- Angular - 表单验证
- Angular Service Workers & PWA
- Angular - Service Workers & PWA
- Angular 测试
- Angular - 测试概述
- Angular NgModules
- Angular - 模块介绍
- Angular 高级
- Angular - 身份验证和授权
- Angular - 国际化
- Angular - 可访问性
- Angular - Web Workers
- Angular - 服务器端渲染
- Angular - Ivy 编译器
- Angular - 使用 Bazel 构建
- Angular - 向后兼容性
- Angular - 响应式编程
- Angular - 指令和组件之间的数据共享
- Angular 工具
- Angular - CLI
- Angular 其他
- Angular - 第三方控件
- Angular - 配置
- Angular - 显示数据
- Angular - 装饰器和元数据
- Angular - 基本示例
- Angular - 错误处理
- Angular - 测试和构建项目
- Angular - 生命周期钩子
- Angular - 用户输入
- Angular - 最新动态?
- Angular 有用资源
- Angular - 快速指南
- Angular - 有用资源
- Angular - 讨论
Angular - 响应
HTTP 响应
在 HTTP 协议中,响应是服务器为客户端请求的特定资源返回的数据。响应将遵循与请求相同的模式。它有一个头部和一个主体。头部包含有关响应的元信息,主体包含实际的响应。
HttpEvent 类
HttpClient 将请求发送到服务器并捕获来自服务器的响应。然后,它将响应包含在一个对象中,该对象根据请求配置具有以下可能的类型。
- HttpEvent
- HttpSentEvent
- HttpUserEvent
- HttpProgressEvent
- HttpResponseBase
- HttpHeaderResponse
- HttpResponse
实际上,HttpEvent 是所有其他类的并集,如下所示:
type HttpEvent<T> = HttpSentEvent | HttpHeaderResponse | HttpResponse<T> | HttpProgressEvent | HttpUserEvent<T>;
让我们在本节中逐一了解 Angular 提供的响应类型。
HttpSentEvent
HttpSentEvent 用于指定请求已发送到服务器。当请求多次重试时,它将非常有用。
interface HttpSentEvent { type: HttpEventType.Sent }
HttpUserEvent
HttpUserEvent 用于标识响应的事件是用户定义的。它将有助于将所有自定义事件分组到一个类别中。它将确保所有拦截器都能正确处理和转发事件。
interface HttpUserEvent<T> { type: HttpEventType.User }
HttpProgressEvent
HttpProgressEvent 用于标识请求是基于下载还是基于上传。此外,它还将在下载/上传功能期间包含当前已加载的字节。
interface HttpProgressEvent { type: HttpEventType.DownloadProgress | HttpEventType.UploadProgress loaded: number total?: number }
这里:
loaded 用于引用已上传/下载的字节数
total 用于引用要下载/上传的总数据量
HttpResponseBase
HttpResponseBase 是 HttpHeaderResponse 和 HttpResponse 的基类。它包含有关响应的基本信息。
abstract class HttpResponseBase { constructor() // have not shown full details for understanding purpose headers: HttpHeaders status: number statusText: string url: string | null ok: boolean type: HttpEventType.Response | HttpEventType.ResponseHeader }
这里:
headers - 作为 HttpHeaders 对象的响应头信息
status - 用于引用请求的不同状态的数字
statusText - 用于引用请求的不同状态的文本
url - 请求的 URL
ok - 请求的成功/失败
type - 事件的类型(Response 或 ResponseHeader)
HttpHeaderResponse
HttpHeaderResponse 继承自 HttpResponseBase,并包含一个克隆响应的选项。该类的目的是包含带有头部和状态信息的响应,而跳过响应的实际主体。它只有一个 clone() 方法,用于获取头部信息的副本,以便更新头部信息。
let response = res.clone(update: { })
这里:
res 是从服务器返回的响应对象。
update 是一个对象,其中包含要在响应的头部中更新的数据。
HttpResponse
HttpResponse 继承自 HttpResponseBase,并包含响应的主体和克隆响应的选项。该类的目的是包含带有主体、头部和状态信息的响应。它只有一个 clone() 方法,用于获取整个响应的副本,以便更新响应信息。
可以使用 body 属性获取响应的主体,如下所示:
let body = res.body;
这里:
res 是从服务器返回的响应对象。
body 是保存来自服务器的实际响应的属性。
克隆响应的方法与 HttpHeaderResponse 类似,如下所示:
let response = res.clone(update: { })
这里:
res 是从服务器返回的响应对象。
update 是一个对象,其中包含要在响应的头部中更新的数据。
工作示例
让我们创建一个示例 Web 应用程序,将文件上传到服务器。我们将创建一个用于上传文件的 api,然后从 Angular 前端应用程序调用它。在应用程序开发过程中,我们将学习不同类型的响应。
首先,让我们创建一个新的 express 应用程序来将文件上传到服务器。
步骤 1:转到您喜欢的 workspace,如下所示:
cd /go/to/your/favorite/workspace
步骤 2:创建一个新文件夹 expense-rest-api 并进入该文件夹
mkdir upload-rest-api && cd upload-rest-api
步骤 3:使用 npm 命令提供的 init 子命令创建一个新应用程序,如下所示:
npm init
上述命令会提出一些问题,请使用默认答案回答所有问题。
步骤 4:安装 express 和 cors 包以创建基于节点的 Web 应用程序。
npm install express cors multer --save
这里:
express 是一个用于创建 Web 应用程序的 Web 框架
cors 是一个用于处理 HTTP 应用程序中 CORS 概念的中间件
multer 是另一个用于处理文件上传的中间件
步骤 5:打开 index.js 并更新以下代码:
var express = require("express") var cors = require('cors') const multer = require('multer'); 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)) }); const storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, "uploads/") }, filename: (req, file, cb) => { cb(null, Date.now() + "-" + file.originalname) }, }) const upload = multer({ storage: storage }); app.post('/api/upload', upload.single('photo'), (req, res) => { console.log(req.file) res.json({ message: 'File uploaded successfully!' }); });
这里:
通过启用 cors、multer 和 body 解析器中间件来配置一个简单的 express 应用程序。
创建了一个新的 api /api/upload 来接受文件并将其存储在服务器上的 uploads 文件夹中。
将上传文件夹配置为 uploads
该 api 将接受名为 photo 的文件输入
步骤 6:创建一个用于存储上传文件的目录。
mkdir uploads
步骤 7:运行应用程序,如下所示:
node index.js
步骤 8:要测试应用程序并确保其正常工作,请使用 postman、curl 或任何其他 HTTP 客户端工具包。我们可以向 api 端点 https://127.0.0.1:8000/api/upload 创建一个新请求,其中 photo 为文件类型的表单输入,并将文件附加到表单输入。
让我们创建一个可工作的 Angular 示例,使用 HttpClient 服务类和 HttpRequest 选项从服务器获取所有费用项目。
步骤 1:通过运行 ng new 命令创建一个新的 Angular 应用程序,如下所示:
ng new my-upload-app
启用 Angular 路由和 CSS,如下所示:
? Would you like to add Angular routing? Yes ? Which stylesheet format would you like to use? CSS
步骤 2:通过在模块配置文件 (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 部分。
步骤 3:创建一个新组件 Upload 来显示来自服务器的费用项目。
ng generate component upload
它将创建如下所示的组件:
CREATE src/app/upload/upload.component.css (0 bytes) CREATE src/app/upload/upload.component.html (21 bytes) CREATE src/app/upload/upload.component.spec.ts (559 bytes) CREATE src/app/upload/upload.component.ts (202 bytes) UPDATE src/app/app.module.ts (554 bytes)
步骤 4:将我们的新组件包含到 App 根组件的视图 app.component.html 中,如下所示:
<app-upload></app-upload> <router-outlet></router-outlet>
步骤 5:通过构造函数将 HttpClient 注入到 Upload 组件中,并从 rxjs 和 Angular 模块导入必要的类,如下所示:
import { Component } from '@angular/core'; import { HttpClient, HttpEvent, HttpEventType } from '@angular/common/http'; import { Observable, map } from 'rxjs'; @Component({ selector: 'app-upload', templateUrl: './upload.component.html', styleUrls: ['./upload.component.css'] }) export class UploadComponent { constructor(private http: HttpClient) { } }
步骤 6:创建一个变量来保存要上传的文件,以及另一个变量来保存上传消息。
file?: File | null = null; message : String | null = null;
步骤 7:创建一个函数来获取用户从表单(待创建)上传的文件,并将其存储在 file 变量中。
onFilechange(event: any) { let files = event.target.files this.file = files.item(0) console.log(this.file) }
这里:
event 是保存上传事件信息的事件对象。event.target.files 保存上传的文档。
步骤 8:创建一个函数 getEventMessage() 来打印上传事件信息。
private getEventMessage(event: HttpEvent, file?: File) { let message : String | null = null; switch (event.type) { case HttpEventType.Sent: message = `Uploading file "${file?.name}" of size ${file?.size}.`; console.log(message); return message; case HttpEventType.UploadProgress: // Compute and show the % done: const percentDone = event.total ? Math.round(100 * event.loaded / event.total) : 0; message = `File "${file?.name}" is ${percentDone}% uploaded.`; console.log(message); return message; case HttpEventType.Response: message = `File "${file?.name}" was completely uploaded!`; console.log(message); return message; default: message = `File "${file?.name}" surprising upload event: ${event.type}.`; console.log(message); return message; } }
这里:
switch 语句用于捕获不同的事件并相应地打印它们
HttpEventType 保存信息类型
步骤 9:创建一个函数 upload() 将用户选择的文件上传到服务器。
upload() { const formData: FormData = new FormData(); formData.append('photo', this.file as Blob, this.file?.name); const myObservable: Observable<HttpEvent<any>> = this.http.post<any>('https://127.0.0.1:8000/upload', formData, { observe: 'events', reportProgress: true }); myObservable.pipe( map(data => { console.log(data); return data; }),).subscribe( evt => { this.message = this.getEventMessage(evt, this.file as File) }); }
这里:
formData 保存用户上传的文件。
post() 方法将 formData 中的数据发送到服务器。
myObservable 将使用 map 函数打印服务器返回的数据,并使用 getEventMessage() 函数打印事件信息
步骤 10:upload 组件 (upload.component.ts) 的完整源代码如下:
import { Component } from '@angular/core'; import { HttpClient, HttpEvent, HttpEventType } from '@angular/common/http'; import { Observable, map } from 'rxjs'; @Component({ selector: 'app-upload', templateUrl: './upload.component.html', styleUrls: ['./upload.component.css'] }) export class UploadComponent { file?: File | null = null; message : String | null = null; constructor(private http: HttpClient) { } onFilechange(event: any) { let files = event.target.files this.file = files.item(0) console.log(this.file) } upload() { const formData: FormData = new FormData(); formData.append('photo', this.file as Blob, this.file?.name); const myObservable: Observable<HttpEvent<any>> = this.http.post<any>('https://127.0.0.1:8000/api/upload', formData, { observe: 'events', reportProgress: true }); console.log('Hi'); myObservable.pipe( map(data => { console.log(data); return data; }), ).subscribe( evt => { this.message = this.getEventMessage(evt, this.file as File) }); } private getEventMessage(event: HttpEvent<any>, file?: File) { let message : String | null = null; switch (event.type) { case HttpEventType.Sent: message = `Uploading file "${file?.name}" of size ${file?.size}.`; console.log(message); return message; case HttpEventType.UploadProgress: // Compute and show the % done: const percentDone = event.total ? Math.round(100 * event.loaded / event.total) : 0; message = `File "${file?.name}" is ${percentDone}% uploaded.`; console.log(message); return message; case HttpEventType.Response: message = `File "${file?.name}" was completely uploaded!`; console.log(message); return message; default: message = `File "${file?.name}" surprising upload event: ${event.type}.`; console.log(message); return message; } } }
步骤 11:在组件的模板('upload.component.html')中创建一个上传表单,并为上传按钮的 click 事件设置 upload() 方法。
<div><h3>Uploads</h3></div> <form enctype="multipart/form-data"> <label for="formFile" class="form-label">Upload file example</label> <input type="file" name="photo" id="file" (change)="this.onFilechange($event)" /> <div *ngIf="file"> <section class="file-info"> File details: <ul> <li>Name: {{file.name}}</li> <li>Type: {{file.type}}</li> <li>Size: {{file.size}} bytes</li> </ul> </section> <p *ngIf="message">{{message}}</p> <button (click)="this.upload()" type="button">Upload</button> </div> </form>
步骤 12:最后,使用以下命令运行应用程序:
ng serve
步骤 13:打开浏览器并导航到 https://127.0.0.1:4200/ URL 并检查输出
这里,输出显示表单。选择一个大约 30 MB 的大文件并尝试上传它,如下所示:
输出显示浏览器及其控制台中服务器返回的所有事件。
结论
Angular 提供了不同的类和类型来正确包含来自服务器的响应数据。所有类都易于学习、理解和操作响应,然后将其显示在网站/应用程序中。