【TypeScript】异步编程

news2024/9/28 5:30:00

文章目录

  • 异步编程
    • 1. TypeScript 中的异步编程
      • 1.1 基本用法
        • 简单的异步函数
        • 异步操作与延迟
        • 并行执行多个异步操作
        • 处理错误
        • 使用 Promise.all 处理多个异步操作的错误
    • 2. 在 TypeScript 中使用 Vite 和 FastAPI
      • 2.1 安装 Node.js
      • 2.2 创建 Vue 3 + TypeScript 项目
      • 2.3 安装依赖
      • 2.4 启动开发服务器
      • 2.5 单文件组件
        • HelloWorld.vue 示例
      • 2.6 FastAPI 后端
        • 安装 FastAPI
        • 交互式 API 文档
      • 2.7 发起 POST 请求
        • 修改后的 HelloWorld.vue
        • 更新后的 FastAPI 后端
      • 2.8 测试
    • 3. 封装 Axios 的必要性与实现
      • 3.1 为什么要封装 Axios
      • 3.2 Axios 类型声明
        • 封装 Axios 实例
      • 3.3 创建 API 管理文件
        • type.ts 示例
        • api.ts 示例
      • 3.5 在组件中使用 API
        • 使用方式一:顶层 `await`
        • 使用方式二:函数内 `async/await`
    • 学习总结

异步编程

1. TypeScript 中的异步编程

在 TypeScript 中,异步编程通常通过 asyncawait 关键字来实现,这使得处理异步操作更加优雅和直观。这些特性是基于 ES2017(ES8)标准的,允许我们编写可读性更强的异步代码。

1.1 基本用法

简单的异步函数

首先,我们定义一个简单的异步函数,它返回一个 Promise 对象:

async function greet(): Promise<string> {
    return Promise.resolve("Hello, async world!");
}

async function execute() {
    const message = await greet();
    console.log(message); // 输出: Hello, async world!
}

execute();

在这个例子中,greet 函数是异步的,返回一个 Promiseexecute 函数使用 await 来获取 greet 函数的结果。

异步操作与延迟

我们可以模拟一个延迟操作,例如从服务器获取数据:

async function fetchData(): Promise<number> {
    return new Promise((resolve) => {
        setTimeout(() => resolve(42), 500); // 500 毫秒后返回 42
    });
}

async function run() {
    const data = await fetchData();
    console.log(data); // 输出: 42
}

run();

这里的 fetchData 函数在 500 毫秒后解决,并返回一个数字。

并行执行多个异步操作

我们可以并行执行多个异步函数,使用 Promise.all

async function fetchFirstValue(): Promise<number> {
    return new Promise((resolve) => {
        setTimeout(() => resolve(10), 1000);
    });
}

async function fetchSecondValue(): Promise<number> {
    return new Promise((resolve) => {
        setTimeout(() => resolve(20), 1000);
    });
}

async function execute() {
    const [first, second] = await Promise.all([fetchFirstValue(), fetchSecondValue()]);
    console.log(first + second); // 输出: 30
}

execute();

在这个示例中,两个异步操作同时执行,最后将它们的结果相加。

处理错误

可以通过 try...catch 块来捕获异步函数中的错误:

async function faultyOperation(): Promise<number> {
    throw new Error("An error occurred");
}

async function run() {
    try {
        const result = await faultyOperation();
    } catch (error) {
        console.error(error.message); // 输出: An error occurred
    }
}

run();

这里,faultyOperation 函数抛出一个错误,我们在 run 函数中捕获并处理它。

使用 Promise.all 处理多个异步操作的错误

如果多个异步操作中有一个失败,可以使用 Promise.all 来处理:

async function failOperation(): Promise<number> {
    return new Promise((_, reject) => {
        setTimeout(() => reject('Operation failed'), 300);
    });
}

async function successOperation(): Promise<number> {
    return new Promise((resolve) => {
        setTimeout(() => resolve(25), 300);
    });
}

async function run() {
    try {
        const [result1, result2] = await Promise.all([failOperation(), successOperation()]);
        console.log(result1 + result2);
    } catch (error) {
        console.error(error); // 输出: Operation failed
    }
}

run();

在这个示例中,failOperation 将会拒绝,而 Promise.all 会立即捕获这个拒绝,并在 run 函数中处理。

2. 在 TypeScript 中使用 Vite 和 FastAPI

2.1 安装 Node.js

确保你已经安装了 Node.js(推荐使用最新的稳定版)。然后在命令行中运行以下命令来全局安装 Vite:

npm install -g create-vite

2.2 创建 Vue 3 + TypeScript 项目

使用 Vite 创建一个新的 Vue 3 + TypeScript 项目,运行以下命令并替换 vue3ts 为你的项目名称:

create-vite vue3ts --template vue-ts

2.3 安装依赖

进入项目目录并安装依赖:

cd vue3ts
npm install

2.4 启动开发服务器

启动开发服务器:

npm run dev

在浏览器中输入 http://localhost:5173/,如果能看到页面,则说明环境搭建成功。

2.5 单文件组件

打开文件 src/components/HelloWorld.vue,我们将开始修改这个单文件组件。

HelloWorld.vue 示例
<template>
    <button @click="get_query()">发起GET请求</button>
</template>

<script setup lang='ts'>
import axios from 'axios';

interface TestData {
    message: string;
}

const get_query = () => {
    // 发起 GET 请求
    axios.get<TestData>('http://127.0.0.1:8009/')
        .then(response => {
            const testData: TestData = response.data;
            console.log(testData.message);
        })
        .catch(error => {
            console.error(error);
        });
}
</script>

2.6 FastAPI 后端

确保你使用 Python 3.8 以上版本(推荐 Python 3.10.5)。检查 Python 版本:

import sys
print(sys.version)
安装 FastAPI

安装 FastAPI:

pip install fastapi -i https://pypi.tuna.tsinghua.edu.cn/simple

FastAPI 会自动安装 Uvicorn。创建一个 test.py 文件并粘贴以下代码:

import uvicorn
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=False,
    allow_methods=["*"],
    allow_headers=["*"]
)

@app.get("/")
async def root():
    return {"message": "Hello World"}

if __name__ == '__main__':
    uvicorn.run(app, host='0.0.0.0', port=8009)

test.py 所在目录打开终端,运行:

python test.py

访问地址为 http://127.0.0.1:8009/,你将看到如下 JSON 响应:

{"message": "Hello World"}
交互式 API 文档

在浏览器中输入 http://127.0.0.1:8009/docs,查看自动生成的交互式 API 文档。

2.7 发起 POST 请求

修改 HelloWorld.vue,实现 POST 请求的功能。

修改后的 HelloWorld.vue
<template>
    <button @click="get_query()">发起POST请求</button>
</template>

<script setup lang='ts'>
import axios from 'axios';

interface TestData {
    item_id: string;
    name: string;
}

const get_query = () => {
    // 发起 POST 请求
    axios.post<TestData>('http://127.0.0.1:8009/items/', { item_id: "5", name: "hello" })
        .then(response => {
            const testData: TestData = response.data;
            console.log(testData.item_id);
            console.log(testData.name);
        })
        .catch(error => {
            console.error(error);
        });
}
</script>
更新后的 FastAPI 后端
from fastapi import Body, FastAPI
from fastapi.middleware.cors import CORSMiddleware
from typing import Annotated

app = FastAPI()
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=False,
    allow_methods=["*"],
    allow_headers=["*"]
)

@app.post("/items/")
async def read_item(item_id: Annotated[int, Body()], name: Annotated[str, Body()]):
    return {"item_id": item_id, "name": name}

2.8 测试

按 F12 打开浏览器控制台,点击按钮后,控制台将看到输出:

5
hello

这样,你的前端与后端交互已成功实现。

3. 封装 Axios 的必要性与实现

3.1 为什么要封装 Axios

封装 Axios 主要是为了利用 TypeScript 的优势,确保类型检查和语法提示,从而提高代码的安全性和便捷性。具体而言,封装的好处包括:

  1. 统一处理请求头:通过创建 Axios 实例,可以集中管理请求头,避免每次请求都重复设置。

  2. 接口统一管理:将所有接口集中管理,使代码更清晰,易于维护,避免重复的代码。

  3. 避免回调地狱:使用 async/await 语法,提高代码的可读性,避免嵌套的 .then() 结构。

3.2 Axios 类型声明

Axios 提供了完备的类型声明,允许我们在 TypeScript 中准确地定义请求和响应的数据类型。核心方法如 requestgetpost 都支持泛型,从而使得我们可以指定响应数据的类型。

封装 Axios 实例

src 文件夹下创建一个 request 文件夹,并添加 base.ts 文件:

import axios from 'axios';

// 创建 axios 实例
const instance = axios.create({
    baseURL: '', // 请求地址前缀
    timeout: 80000, // 请求超时时间
    withCredentials: true, // 异步请求携带 cookie
});

// 请求拦截器
instance.interceptors.request.use(
    config => {
        // 可在此添加 token
        return config;
    },
    error => Promise.reject(error)
);

// 响应拦截器
instance.interceptors.response.use(
    response => response.data,
    error => {
        if (error.response.status === 401) {
            localStorage.removeItem("x-auth-token");
            // 可在此跳转登录页
        }
        return Promise.reject(error);
    }
);

export default instance;

3.3 创建 API 管理文件

request 文件夹下,为不同模块创建文件夹,比如 user,并添加 type.tsapi.ts 文件。

type.ts 示例
export interface ReqLogin {
    username: string;
    password: string;
}

export interface ProData {
    projects?: string;
    detail?: { code: number; message: string; data: string };
}

export interface ItypeAPI {
    id: number;
    username: string;
    email: string;
    token: string;
}
api.ts 示例
import instance from "../base";
import { ReqLogin, ProData, ItypeAPI } from "./type";

const headers = { "content-type": "application/x-www-form-urlencoded" };

// 登录请求
export const loginAPI = (data: ReqLogin): Promise<ItypeAPI> =>
    instance.post("/v1/users/token", data, { headers });

export const checkAPI = (): Promise<ProData> =>
    instance.get("/v1/users/pro", { headers });

3.5 在组件中使用 API

使用方式一:顶层 await
<script setup lang="ts">
import { checkAPI } from "../../request/api";

let res = await checkAPI();
console.log(res);
</script>
使用方式二:函数内 async/await
<script setup lang="ts">
import { loginAPI } from '../request/user/api';

const data = { username: "mockuser", password: "123456" };

const get_query = async () => {
    let res = await loginAPI(data);
    console.log(res);
};
</script>

通过这样的封装,可以有效地提升代码的可读性和维护性,同时利用 TypeScript 提供的强类型检查,确保数据的安全性。

学习总结

使用 asyncawait,我们可以以一种更简洁和可读的方式编写异步代码。通过捕获错误和并行处理多个操作,我们可以确保代码的稳定性和可靠性。
最后一章居然讲解了axiso的源码,我哭死。本人亦因此开启了阅读前端框架源码的习惯。通过封装axiso,可以有效地提升代码的可读性和维护性,同时利用 TypeScript 提供的强类型检查,确保数据的安全性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2172480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c++day08

思维导图 栈 #include <iostream>using namespace std;template <typename T> class Stack { private:static const size_t MAX 100; // 定义固定容量T data[MAX]; // 存储栈元素的数组size_t len; // 当前栈的大小public:…

华为玄玑感知系统震撼发布:智能穿戴新品引领情绪健康新纪元

在科技日新月异的今天&#xff0c;华为再次以其卓越的创新能力&#xff0c;为智能穿戴领域带来了一场革命性的变革。 8月28日&#xff0c;华为玄玑感知系统暨穿戴创新技术发布会圆满落幕&#xff0c;会上正式揭晓了这款名为“玄玑”的神秘感知系统&#xff0c;预示着穿戴设备将…

9.26 Buu俩题解

[CISCN2019 华东北赛区]Web2 看wp写完之后写的 知识点 存储型XSS与过滤绕过sql注入 题解 好几个页面&#xff0c;存在登录框可以注册&#xff0c;存在管理员页面(admin.php) ->既然存在管理员页面&#xff0c;且直接访问admin.php提示我们 说明存在身份验证&#xff0…

【深度学习】低维向量映射到高维空间的方法

低维向量映射到高维空间的方法 1、全连接层&#xff08;线性层&#xff09;&#xff1a; 全连接层&#xff0c;也称为线性层&#xff0c;是神经网络中最基本的组件之一。它通过一个权重矩阵和一个偏置向量对输入向量进行线性变换。如果输入向量的维度是 din&#xff0c;而我们…

Splashtop 加入 Microsoft 智能安全协会

2024年9月25日 美国加利福尼亚州库比蒂诺 Splashtop Inc . 今天宣布已正式加入 Microsoft 智能安全协会&#xff08;MISA&#xff09;。MISA 由独立软件供应商&#xff08;ISV&#xff09;和托管安全服务提供商&#xff08;MISA&#xff09;组成&#xff0c;他们将其解决方案与…

无人机之视觉导航算法篇

一、图像采集与预处理 图像采集&#xff1a;无人机通过其搭载的摄像头或其他视觉传感器实时采集周围环境的图像信息。 图像预处理&#xff1a;对采集到的图像进行预处理&#xff0c;包括滤波、降噪、增强等操作&#xff0c;以提高图像的质量和清晰度&#xff0c;为后续的特征…

Linux当中的权限问题

文章目录 一、Linux权限的概念1. Linux中的用户分类2. 不同用户之间的转换(1) 普通用户->root(2) root->普通用户(3) 普通用户->普通用户 二、Linux权限管理1. 文件访问者的分类2. 文件类型和访问权限&#xff08;1&#xff09;文件后缀在Linux中的作用&#xff08;2&…

三个视觉领域常用数据标注工具:labelImg 解压安装基础使用、 label-studio 的安装和基础使用【检测数据标注】

&#x1f947; 版权: 本文由【墨理学AI】原创、在CSDN首发、各位大佬、敬请查阅&#x1f389; 声明: 作为全网 AI 领域 干货最多的博主之一&#xff0c;❤️ 不负光阴不负卿 ❤️ 本次博文主要对如下三个视觉领域常用数据标注工具进行初步整理 labelImglabel-studio 工具Robo…

生成式AI如何辅助医药行业智能营销

生成式AI在医药行业的智能营销中发挥着日益重要的作用&#xff0c;它通过多种方式辅助医药企业提升市场洞察能力、优化营销策略、增强客户互动和体验&#xff0c;从而推动销售增长和品牌价值的提升。以下是生成式AI如何辅助医药行业智能营销的具体方式&#xff1a;一、精准市场…

微软Win11 22H2/23H2 九月可选更新KB5043145发布!

系统之家于9月27日发出最新报道&#xff0c;微软针对Windows11系统&#xff0c;发布了九月最新可选更新补丁KB5043145&#xff0c;22H2用户安装后&#xff0c;系统版本号升至22621.4249&#xff0c;23H2用户安装后升至22631.4249。本次更新修复了Edge使用IE模式有时会停止响应等…

JS逆向基础-谷歌浏览器调试技巧(详细)

概述 浏览器的调试工具在 JavaScript 逆向工程中&#xff0c;帮助开发者分析和理解代码执行流程、变量值及其变化&#xff0c;从而揭示隐藏逻辑和加密机制&#xff0c;为破解、修改或复现代码提供重要支持。 调试面板详解 谷歌浏览器的调试面板概览&#xff1a; 顶部操作栏 …

直线模组降噪攻略

直线模组作为现代机械自动化中不可或缺的重要组件&#xff0c;其性能与稳定性直接影响到整个设备的运行效果。在使用过程中&#xff0c;直线模组有时会出现噪音&#xff0c;可能由多种因素导致&#xff0c;当噪音出现时&#xff0c;可以试试以下几个方法&#xff1a; 1、设备选…

Apache Iceberg 数据类型参考表

Apache Iceberg 概述-链接 Apache Iceberg 数据类型参考表 数据类型描述实例方法注意事项BOOLEAN布尔类型&#xff0c;表示真或假true, false用于条件判断&#xff0c;例如 WHERE is_active true。确保逻辑条件的正确性。INTEGER32位有符号整数42, -7可用于计算、聚合&#xf…

检查一个CentOS服务器的配置的常用命令

在CentOS系统中&#xff0c;查看服务器配置的常用命令非常丰富&#xff0c;这些命令可以帮助用户快速了解服务器的硬件信息、系统状态以及网络配置等。以下是一些常用的命令及其简要说明&#xff1a; 1. 查看CPU信息 (1) cat /proc/cpuinfo&#xff1a;显示CPU的详细信息&…

【YashanDB知识库】如何dump数据文件,转换rowid, 查询对应内容

本文来自YashanDB官网&#xff0c;具体内容可见https://www.yashandb.com/newsinfo/7459464.html?templateId1718516 问题现象 客户环境有时候会遇到文件损坏的情况&#xff0c;需要dump文件&#xff0c;根据rowid查询数据情况。 问题的风险及影响 熟练掌握崖山数据文件du…

ROS理论与实践学习笔记——2 ROS通信机制之通信机制实践

5.1 话题发布 需求描述&#xff1a;编码实现乌龟运动控制&#xff0c;让小乌龟做圆周运动。 实现分析&#xff1a; ①乌龟运动控制实现&#xff0c;关键节点有两个&#xff0c;一个是乌龟运动显示节点 turtlesim_node&#xff0c;另一个是控制节点&#xff0c;二者是订阅发布模…

公交换乘C++

题目&#xff1a; 样例解释&#xff1a; 样例#1&#xff1a; 第一条记录&#xff0c;在第 3 分钟花费 10 元乘坐地铁。 第二条记录&#xff0c;在第 46 分钟乘坐公交车&#xff0c;可以使用第一条记录中乘坐地铁获得的优惠票&#xff0c;因此没有花费。 第三条记录&#xff0c;…

基于微信小程序的智慧社区的设计与实现

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

docker拉取镜像失败

docker拉取镜像失败 错误提示检查linux服务器是否开通防火墙开放端口重启防火墙查看已开放的端口 修改配置文件 错误提示 检查linux服务器是否开通防火墙 firewall-cmd --staterunning表示防火墙正在运行&#xff0c;显示not running表示未运行&#xff0c;使用以下命令开启防…

vite 底层解析

vite 目前大多数框架的前端构建工具都已经被vite取代&#xff0c;相信你已经使用过vite了。可是在使用过程中&#xff0c;vite对我来说一直是模糊的&#xff0c;现在就来一探究竟&#xff0c;为啥它更好&#xff1f; 接下来我将为从以下几点出发&#xff0c;究其原理 一、原生…