引言
大家好,我是GISer Liu😁,一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年9月学习赛的TypeScript学习总结文档。本文旨在全面介绍 TypeScript 中的异步编程与网络请求,帮助读者深入理解 TypeScript 中的
async/await
、Promise、Fetch API、Axios、请求拦截器、响应拦截器、跨域处理等概念,以及在实际开发中的应用。💕💕😊
介绍
1.异步编程
在现代 Web 开发中,异步编程已经成为不可或缺的一部分。无论是从服务器获取数据、处理用户输入,还是执行复杂的计算任务,异步编程都能显著提升应用的性能和用户体验。
想象一下,如果一个网页在加载数据时需要等待所有操作完成才能继续,用户将会面临长时间的等待和卡顿,这显然是不可接受的。
异步编程的核心思想是允许程序在等待某些操作完成的同时,继续执行其他任务。这种方式不仅提高了程序的响应速度,还避免了因长时间等待而导致的资源浪费。
在 JavaScript 生态系统中,异步编程尤为重要,因为它是一种单线程语言,如果不采用异步机制,程序很容易陷入阻塞状态。
在TypeScript中,我们主要通过Promise和async/await进行一步编程,后者是前者的简化语法糖,具体内容我们在对应模块中进行详细介绍;
2.网络请求
在当下主流 Web 应用开发中,网络请求是获取和发送数据的重要手段。无论是从服务器获取数据,还是向服务器提交表单,网络请求都是不可或缺的。
在 TypeScript 中,常用的网络请求方法包括 XHR
,fetch
和 axios
。它们的本质都是通过 HTTP 协议与服务器进行通信。fetch
和 axios
都基于 Promise
,支持异步操作,使得我们可以使用 async/await
来简化异步代码的编写。
网络请求常常和异步编程相伴出现;这里作者联合两者,读者可以有一个更好的理解;
下面作者将两个模块分别进行描述!😘
一. TypeScript 中的异步编程模块
1.TypeScript 编译器与 ES5 标准
① TypeScript 默认使用 ES5 标准
TypeScript 是一种强类型的 JavaScript 超集,它通过编译器将 TypeScript 代码转换为 JavaScript 代码。默认情况下,TypeScript 编译器会将代码编译为 ES5 标准,以确保生成的 JavaScript 代码在大多数现代浏览器中都能正常运行。
ES5(ECMAScript 5)是 JavaScript 的一个早期标准,发布于 2009 年。尽管 ES5 提供了许多基础功能,但它并不包含一些现代 JavaScript 特性,如
Promise
对象和async/await
语法。
② ES5 标准中不包含 Promise 对象
在 ES5 标准中,JavaScript 并没有内置的 Promise
对象。Promise
是 ES6(ECMAScript 2015)引入的一个重要特性,用于处理异步操作。Promise
提供了一种更优雅的方式来处理异步操作的结果和错误,避免了传统的回调函数嵌套(即回调地狱)。
由于 TypeScript 默认编译为 ES5,因此在编写 TypeScript 代码时,如果需要使用 Promise
,通常需要确保编译目标为 ES6 或更高版本。可以通过在 tsconfig.json
文件中设置 target
属性来指定编译目标:
{
"compilerOptions": {
"target": "ES6"
}
}
2. async/await
简介
① async/await
是 ES2017(ES8)的特性
async/await
是 ES2017(ES8)引入的语法特性,它建立在 Promise
之上,旨在进一步简化异步编程。async/await
允许开发者以同步代码的方式编写异步操作,从而提高代码的可读性和可维护性。
async
关键字用于声明一个异步函数,await
关键字用于等待一个Promise
的解析结果。await
只能在async
函数内部使用,它会使函数暂停执行,直到Promise
被解析或拒绝。
② async/await
如何简化异步编程
async/await
的主要优势在于它能够将异步代码转换为看起来像同步代码的形式,从而避免了回调地狱和复杂的 Promise 链式调用。以下是一个简单的示例,展示了如何使用 async/await
来处理异步操作:
// 定义一个返回 Promise 的异步函数
async function fetchData(): Promise<string> {
return new Promise((resolve) => {
setTimeout(() => {
resolve("Data fetched successfully!");
}, 1000);
});
}
// 使用 async/await 调用异步函数
async function main() {
try {
const result = await fetchData();
console.log(result); // 输出: Data fetched successfully!
} catch (error) {
console.error("Error fetching data:", error);
}
}
main();
其中,
fetchData
函数返回一个Promise
,模拟了一个异步操作。在main
函数中,我们使用await
关键字等待fetchData
的结果,并将其赋值给result
变量。如果fetchData
成功,result
将包含解析后的值;如果失败,错误将被捕获并在catch
块中处理。
3.使用 async/await
实现异步操作
①处理异步操作的延迟
在实际开发中,异步操作通常涉及网络请求、文件读取等需要时间完成的任务。我们可以使用 setTimeout
来模拟这些延迟操作。
// 定义一个返回 Promise 的异步函数,模拟延迟操作
async function asyncOperation(): Promise<number> {
return new Promise((resolve) => {
setTimeout(() => {
resolve(10);
}, 1000); // 延迟 1000 毫秒(1 秒)
});
}
// 使用 async/await 调用异步函数
async function run() {
const result = await asyncOperation();
console.log(result); // 输出: 10
}
run();
asyncOperation
函数返回一个Promise
,该Promise
会在 1000 毫秒后解析并返回数字10
。在
run
函数中,我们使用await
关键字等待asyncOperation
的结果。await
会使run
函数暂停执行,直到asyncOperation
返回的Promise
被解析。一旦Promise
被解析,result
变量将包含解析后的值,即10
。
②串行执行多个异步操作
在某些场景下,我们需要按顺序执行多个异步操作,例如预先加载多个数据。await
关键字可以确保这些操作按顺序执行,即在前一个操作完成后再执行下一个操作。
// 定义两个返回 Promise 的异步函数,模拟延迟操作
async function asyncOperation1(): Promise<number> {
return new Promise((resolve) => {
setTimeout(() => {
resolve(10);
}, 1000); // 延迟 1000 毫秒(1 秒)
});
}
async function asyncOperation2(): Promise<number> {
return new Promise((resolve) => {
setTimeout(() => {
resolve(20);
}, 1000); // 延迟 1000 毫秒(1 秒)
});
}
// 使用 async/await 串行执行多个异步操作
async function run() {
const result1 = await asyncOperation1();
const result2 = await asyncOperation2();
console.log(result1 + result2); // 输出: 30
}
run();
这里我们定义了两个异步函数 asyncOperation1
和 asyncOperation2
,它们分别返回一个 Promise
,并在 1000 毫秒后解析。在 run
函数中,我们使用 await
关键字按顺序等待这两个异步操作的结果。await
确保 asyncOperation1
完成后才会执行 asyncOperation2
,从而实现了串行执行。
通过这种方式可以避免数据还没有加载就执行了数据展示或处理的程序引发的报错!
③ 处理异步操作中的错误
在异步操作中,错误处理是非常重要的。我们可以使用 try...catch
块来捕获和处理异步操作中的错误。
// 定义一个返回 Promise 的异步函数,模拟可能出错的异步操作
async function asyncOperation(): Promise<number> {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("Something went wrong"));
}, 1000); // 延迟 1000 毫秒(1 秒)
});
}
// 使用 async/await 调用异步函数,并使用 try...catch 块捕获错误
async function run() {
try {
const result = await asyncOperation();
console.log(result);
} catch (error) {
console.error(error.message); // 输出: Something went wrong
}
}
run();
asyncOperation
函数返回一个Promise
,该Promise
会在 1000 毫秒后被拒绝,并抛出一个错误。在run
函数中,我们使用try...catch
块来捕获这个错误。如果asyncOperation
成功,result
变量将包含解析后的值;如果失败,错误将被捕获并在catch
块中处理。
错误处理在异步编程中非常重要,因为它可以帮助我们及时发现和处理潜在的问题,避免程序崩溃或产生不可预期的行为。
二、TypeScript中的网络请求模块
1. 网络请求的基本原理
① HTTP 协议
HTTP(Hypertext Transfer Protocol)是一种用于在网络上传输超文本文档的协议。它定义了客户端和服务器之间的通信规范,包括请求格式、响应格式、请求方法、状态码等。
② 请求方法
HTTP 协议定义了几种常见的请求方法,其中最常用的是 GET 和 POST。
- GET 请求:用于从服务器获取数据。GET 请求的参数会附加在 URL 后面,因此不适合传递敏感信息。
- POST 请求:用于向服务器发送数据。POST 请求的参数会放在请求体中,因此适合传递敏感信息和大量数据。
③ 状态码
HTTP 状态码用于表示请求的处理结果。常见的状态码包括:
- 2xx:成功状态码,表示请求成功。例如,200 OK 表示请求成功。
- 3xx:重定向状态码,表示需要进一步操作才能完成请求。例如,301 Moved Permanently 表示资源已永久移动。
- 4xx:客户端错误状态码,表示客户端请求有误。例如,404 Not Found 表示请求的资源不存在。
- 5xx:服务器错误状态码,表示服务器处理请求时出错。例如,500 Internal Server Error 表示服务器内部错误。
2. Fetch API 的使用
Fetch API 是一个现代化的网络请求 API,它基于 Promise,可以用于发送和接收网络请求。
① Fetch API 的基本用法
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
这里我们分析一下这个过程:
1.创建请求:使用
fetch
函数创建一个请求。2.发送请求:
fetch
函数会发送请求到指定的 URL。3.接收响应:服务器返回响应后,
fetch
函数会返回一个Response
对象。4.处理响应:通过
Response
对象的方法(如json()
)处理响应数据,将数据转化为json格式方便处理。5.输出或抛出错误:如果数据如期解析成功,就会在控制台输出数据,如果报错则会输出错误;
② Fetch API 的优缺点
- 优点:语法简单、基于 Promise、支持跨域请求、支持流数据。
- 缺点:兼容性不佳、缺乏细节控制、只能捕获网络错误。
3. Axios 的使用
Axios 是一个基于 Promise 的 HTTP 客户端,广泛用于浏览器和 Node.js 环境中。
①Axios 的基本用法
import axios from 'axios';
axios.get('https://api.example.com/data')
.then(response => console.log(response.data))
.catch(error => console.error('Error:', error));
② Axios 的请求流程
- 创建请求:使用
axios
函数创建一个请求。 - 发送请求:
axios
函数会发送请求到指定的 URL。 - 接收响应:服务器返回响应后,
axios
函数会返回一个包含响应数据的 Promise。 - 处理响应:通过
.then()
方法处理响应数据。
③ Axios 的配置选项
Axios 提供了丰富的配置选项,可以用于自定义请求的行为。
axios({
method: 'post',
url: 'https://api.example.com/data',
data: {
firstName: 'John',
lastName: 'Doe'
}
}).then(response => console.log(response.data))
.catch(error => console.error('Error:', error));
④ Axios 的拦截器
Axios 支持请求拦截器和响应拦截器,可以在请求发送前或响应返回后进行额外的处理。
4. 请求拦截器与响应拦截器
①请求拦截器
请求拦截器允许我们在请求发送前对请求配置进行修改或添加额外的逻辑。常见的使用场景包括:
- 添加认证信息:在请求头中添加认证信息(如 JWT Token)。
- 设置全局请求头:为所有请求设置相同的请求头(如
Content-Type
)。 - 请求日志记录:记录请求的详细信息,便于调试和监控。
- 请求重试:在请求失败时自动重试。
假设我们有一个需要认证的 API,每次请求都需要在请求头中添加 JWT Token。通过请求拦截器,我们可以在每次请求前自动添加 Token,而不需要在每个请求中手动设置。
代码如下:
import axios from 'axios';
// 创建一个 Axios 实例
const instance = axios.create({
baseURL: 'https://api.example.com', //设置基础 URL 和最大请求超时时间。
timeout: 10000,
});
// 添加请求拦截器
instance.interceptors.request.use(
(config) => {
// 在发送请求之前做些什么
const token = localStorage.getItem('token'); // 在请求发送前,从 localStorage 中获取 Token,并将其添加到请求头中。然后记录请求配置信息
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
console.log('Request Config:', config);
return config;
},
(error) => {
// 对请求错误做些什么
console.error('Request Error:', error);
return Promise.reject(error);
}
);
// 发送请求
instance.get('/data')
.then(response => console.log(response.data))
.catch(error => console.error('Error:', error));
请求拦截器就讲到这里,更多应用还是得实践尝试!
② 响应拦截器
响应拦截器允许我们在响应返回后对响应数据进行处理或添加额外的逻辑。常见的使用场景包括:
- 统一处理响应数据:对响应数据进行格式化或解密。
- 错误处理:统一处理服务器返回的错误信息。
- 响应日志记录:记录响应的详细信息,便于调试和监控。
- 权限校验:在响应中检查用户权限,并根据权限进行相应的操作。
假设我们的 API 返回的数据格式是 JSON,但在某些情况下,服务器可能会返回错误信息。通过响应拦截器,我们可以在响应返回后统一处理错误信息,并根据错误类型进行相应的操作。
下面是个代码案例:
import axios from 'axios';
// 创建一个 Axios 实例
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000,
});
// 添加响应拦截器
instance.interceptors.response.use(
(response) => {
// 对响应数据做点什么
console.log('Response Data:', response.data);
return response.data;
},
(error) => {
// 对响应错误做点什么
if (error.response) {
// 服务器返回了错误响应
console.error('Server Error:', error.response.data);
switch (error.response.status) {
case 401:
// 未授权,跳转到登录页面
window.location.href = '/login';
break;
case 404:
// 资源未找到,显示错误信息
console.error('Resource Not Found');
break;
default:
// 其他错误,显示通用错误信息
console.error('An error occurred');
}
} else if (error.request) {
// 请求已发送但未收到响应
console.error('No Response Received:', error.request);
} else {
// 其他错误
console.error('Request Error:', error.message);
}
return Promise.reject(error);
}
);
// 发送请求
instance.get('/data')
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
- 成功回调:在响应返回后,记录响应数据并返回处理后的数据。
- 错误回调:在响应发生错误时,根据错误类型进行相应的处理:
- 服务器返回错误响应:根据状态码进行不同的处理(如 401 跳转到登录页面,404 显示资源未找到信息)。
- 请求已发送但未收到响应:记录未收到响应的请求信息。
- 其他错误:记录请求错误信息。
三、案例实践
这里作者基于实现一个全栈案例Demo,下面是技术栈:
- 前端:Vue3 +TypeScript
- 后端:FastAPI + Python
- 网络请求:Axios
1 环境搭建
① 项目创建
Vite 是一个现代化的前端构建工具,它提供了快速的开发体验。我们可以使用 Vite 快速创建一个 Vue 3 + TypeScript 项目。
- 安装 Vite:
npm install -g create-vite
- 创建vite项目
npm create vite
- 选择项目模板:
- 选择 TypeScript 支持:
- 进入项目目录并安装依赖:
② 项目启动
安装完依赖后,可以使用以下命令启动开发服务器:
npm run dev
启动成功!
2. 单文件组件(SFC)
① 介绍 Vue 的单文件组件(SFC)
Vue 的单文件组件(SFC)是一种将模板、逻辑和样式封装在一个文件中的组件格式。SFC 使用 .vue
文件扩展名,通常包含以下三个部分:
<template>
:定义组件的 HTML 模板。<script>
:定义组件的逻辑,通常使用 TypeScript。<style>
:定义组件的样式。
如下图中APP.vue文件内容所示;
② 展示 HelloWorld.vue 组件的代码
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'HelloWorld',
props: {
msg: {
type: String,
required: true,
},
},
});
</script>
<style scoped>
.hello {
font-family: Avenir, Helvetica, Arial, sans-serif;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
3. 引入 Axios 进行网络请求
① 在 TypeScript 中使用 Axios 进行网络请求
首先,我们需要安装 Axios:
npm install axios
② 发起 GET 和 POST 请求
在 Vue 组件中使用 Axios 发起 GET 和 POST 请求:
<template>
<div>
<h1>Axios 案例测试</h1>
<button @click="fetchPosts">获取100篇文章数据</button>
<button @click="fetchPostById">根据文章ID获取文章数据</button>
<button @click="addPost">添加文章</button>
<button @click="fetchCatImage">随机获取1张猫图</button>
<button @click="fetchDogImage">随机返回一张狗子照片</button>
<button @click="fetchRandomImage">返回随机图片</button>
<div v-if="data">
<pre>{{ data }}</pre>
</div>
<div v-if="imageUrl">
<img :src="imageUrl" alt="图片" />
</div>
<div v-if="quote">
<p>{{ quote }}</p>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import axios from 'axios';
export default defineComponent({
name: 'AxiosExample',
data() {
return {
data: null,
imageUrl: null,
quote: null,
};
},
methods: {
async fetchPosts() {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
this.data = JSON.stringify(response.data, null, 2);
} catch (error) {
console.error('获取文章数据失败:', error);
}
},
async fetchPostById() {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/posts/2');
this.data = JSON.stringify(response.data, null, 2);
} catch (error) {
console.error('获取指定文章数据失败:', error);
}
},
async addPost() {
try {
const response = await axios.post('https://jsonplaceholder.typicode.com/posts', {
title: 'foo',
body: 'bar',
userId: 1,
});
this.data = JSON.stringify(response.data, null, 2);
} catch (error) {
console.error('添加文章失败:', error);
}
},
async fetchCatImage() {
try {
const response = await axios.get('https://api.thecatapi.com/v1/images/search?limit=1');
this.imageUrl = response.data[0].url;
} catch (error) {
console.error('获取猫图失败:', error);
}
},
async fetchDogImage() {
try {
const response = await axios.get('https://dog.ceo/api/breeds/image/random');
this.imageUrl = response.data.message;
} catch (error) {
console.error('获取狗子照片失败:', error);
}
},
async fetchRandomImage() {
try {
const response = await axios.get('https://picsum.photos/200/300');
this.imageUrl = response.request.responseURL;
} catch (error) {
console.error('获取随机图片失败:', error);
}
},
},
});
</script>
<style scoped>
/* 你可以在这里添加一些样式 */
</style>
这里由于时间问题,UI相对还是有点粗糙;😂
当然我们这里成功加载了一些公共服务的API,我们也可以自己搭建后端获取数据,下面我们简单介绍一下使用Python语言基于FastAPI框架进行后端搭建的Demo;
4. 使用 FastAPI 搭建后端服务
① 安装和配置 FastAPI
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API。我们可以使用 FastAPI 快速搭建一个后端服务。
- 安装 FastAPI 和 Uvicorn:
pip install fastapi uvicorn
- 创建一个简单的 FastAPI 应用:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# 添加 CORS 中间件,避免跨域错误
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 允许所有来源
allow_credentials=True,
allow_methods=["*"], # 允许所有方法
allow_headers=["*"], # 允许所有头
)
@app.get("/data")
async def get_data():
return {"message": "Hello, World!"}
@app.post("/data")
async def add_data(name: str, age: int):
return {"name": name, "age": age}
- 启动 FastAPI 服务:这里文件名为 main.py
uvicorn main:app --reload
② 后端测试代码
我们可以使用 Postman 或 curl 测试后端服务:
- GET 请求:
curl http://127.0.0.1:8000/data
- POST 请求:
curl.exe -X POST "http://127.0.0.1:8000/data?name=John%20Doe&age=30"
③ 前端与后端的交互
在 Vue 组件中使用 Axios 与 FastAPI 后端进行交互:
这里我们将刚刚的get测试和post测试也加入到vue3程序中;
<template>
<div>
<h1>Axios 案例测试</h1>
<button @click="fetchPosts">获取100篇文章数据</button>
<button @click="fetchPostById">根据文章ID获取文章数据</button>
<button @click="addPost">添加文章</button>
<button @click="fetchCatImage">随机获取1张猫图</button>
<button @click="fetchDogImage">随机返回一张狗子照片</button>
<button @click="fetchRandomImage">返回随机图片</button>
<button @click="fetchLocalData">获取本地数据</button>
<button @click="addLocalData">添加本地数据</button>
<div v-if="data">
<pre>{{ data }}</pre>
</div>
<div v-if="imageUrl">
<img :src="imageUrl" alt="图片" />
</div>
<div v-if="quote">
<p>{{ quote }}</p>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import axios from 'axios';
export default defineComponent({
name: 'AxiosExample',
data() {
return {
data: null,
imageUrl: null,
quote: null,
};
},
methods: {
async fetchPosts() {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
this.data = JSON.stringify(response.data, null, 2);
} catch (error) {
console.error('获取文章数据失败:', error);
}
},
async fetchPostById() {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/posts/2');
this.data = JSON.stringify(response.data, null, 2);
} catch (error) {
console.error('获取指定文章数据失败:', error);
}
},
async addPost() {
try {
const response = await axios.post('https://jsonplaceholder.typicode.com/posts', {
title: 'foo',
body: 'bar',
userId: 1,
});
this.data = JSON.stringify(response.data, null, 2);
} catch (error) {
console.error('添加文章失败:', error);
}
},
async fetchCatImage() {
try {
const response = await axios.get('https://api.thecatapi.com/v1/images/search?limit=1');
this.imageUrl = response.data[0].url;
} catch (error) {
console.error('获取猫图失败:', error);
}
},
async fetchDogImage() {
try {
const response = await axios.get('https://dog.ceo/api/breeds/image/random');
this.imageUrl = response.data.message;
} catch (error) {
console.error('获取狗子照片失败:', error);
}
},
async fetchRandomImage() {
try {
const response = await axios.get('https://picsum.photos/200/300');
this.imageUrl = response.request.responseURL;
} catch (error) {
console.error('获取随机图片失败:', error);
}
},
async fetchLocalData() {
try {
const response = await axios.get('http://127.0.0.1:8000/data');
this.data = JSON.stringify(response.data, null, 2);
} catch (error) {
console.error('获取本地数据失败:', error);
}
},
async addLocalData() {
try {
const response = await axios.post('http://127.0.0.1:8000/data?name=John Doe&age=30');
this.data = JSON.stringify(response.data, null, 2);
} catch (error) {
console.error('添加本地数据失败:', error);
}
},
},
});
</script>
<style scoped>
/* 你可以在这里添加一些样式 */
</style>
经过测试,获取成功!!
如果存在网络问题,看看是不是后端没有配置跨域CORS中间件或者后端项目是否启动;
5. 封装 Axios (可选)
①为什么要封装 Axios
Axios 可以带来以下好处:
- 代码复用:将常用的请求逻辑封装起来,避免重复代码。
- 统一配置:统一管理请求的配置,如基础 URL、请求头、拦截器等。
- 错误处理:统一处理请求错误,减少重复的错误处理逻辑。
- 类型安全:使用 TypeScript 定义接口类型,提升代码的类型安全性。
② 代码实践
- 在 base.ts 文件中创建 Axios 实例
创建一个 base.ts
文件,用于创建 Axios 实例并设置请求和响应拦截器:
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
const instance: AxiosInstance = axios.create({
baseURL: 'http://127.0.0.1:8000',
timeout: 10000,
});
// 请求拦截器
instance.interceptors.request.use(
(config: AxiosRequestConfig) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 响应拦截器
instance.interceptors.response.use(
(response: AxiosResponse) => {
return response.data;
},
(error) => {
return Promise.reject(error);
}
);
export default instance;
③ 定义接口类型
创建一个 type.ts
文件,用于定义接口类型:
export interface DataResponse {
message: string;
}
export interface CreateDataRequest {
name: string;
age: number;
}
export interface CreateDataResponse {
name: string;
age: number;
}
通过定义接口类型,我们可以在编写代码时获得 TypeScript 的类型检查功能,减少类型错误。
④ 封装请求方法
创建一个 api.ts
文件,用于封装请求方法:
import axios from './base';
import { DataResponse, CreateDataRequest, CreateDataResponse } from './type';
export const fetchData = async (): Promise<DataResponse> => {
const response = await axios.get<DataResponse>('/data');
return response;
};
export const createData = async (data: CreateDataRequest): Promise<CreateDataResponse> => {
const response = await axios.post<CreateDataResponse>('/data', data);
return response;
};
在
api.ts
文件中,我们封装了fetchData
和createData
方法,并在方法中使用 TypeScript 的类型注解,确保请求和响应的类型安全。
⑤ 在组件中使用封装的 Axios
在 Vue 组件中直接使用封装的请求方法:
<template>
<div>
<h1>API Example</h1>
<button @click="fetchData">Fetch Data</button>
<button @click="sendData">Send Data</button>
<div v-if="data">
<pre>{{ data }}</pre>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { fetchData, createData } from './api';
export default defineComponent({
name: 'APIExample',
data() {
return {
data: null,
};
},
methods: {
async fetchData() {
try {
this.data = await fetchData();
} catch (error) {
console.error('Error fetching data:', error);
}
},
async sendData() {
try {
this.data = await createData({ name: 'John Doe', age: 30 });
} catch (error) {
console.error('Error sending data:', error);
}
},
},
});
</script>
在 Vue 组件的方法中,我们可以直接使用
await
关键字调用封装的请求方法,简化异步代码的编写。
⑥ 使用 async/await 处理请求
在 Vue 组件的方法中使用 async/await
处理请求:
methods: {
async fetchData() {
try {
this.data = await fetchData();
} catch (error) {
console.error('Error fetching data:', error);
}
},
async sendData() {
try {
this.data = await createData({ name: 'John Doe', age: 30 });
} catch (error) {
console.error('Error sending data:', error);
}
},
}
在
async
函数中,我们可以使用await
关键字等待异步操作完成,并将结果赋值给组件的data
属性。通过这种方式,我们可以更简洁地处理异步请求。
Over,作者的总结完毕!😘👌😊 本次学习总结到此结束!!🙂 各位读者可以参考本文通过代码实践来加深理解!😉
相关链接
- 项目地址:TypeScript-CookBook
- 相关文档:专栏地址
- 作者主页:GISer Liu-CSDN博客
如果觉得我的文章对您有帮助,三连+关注便是对我创作的最大鼓励!或者一个star🌟也可以😂.