0
点赞
收藏
分享

微信扫一扫

长效ip的特征除了稳定还有什么

head-bar

引言


介绍

1.异步编程

在现代 Web 开发中,异步编程已经成为不可或缺的一部分。无论是从服务器获取数据、处理用户输入,还是执行复杂的计算任务,异步编程都能显著提升应用的性能和用户体验。

异步编程的核心思想是允许程序在等待某些操作完成的同时,继续执行其他任务。这种方式不仅提高了程序的响应速度,还避免了因长时间等待而导致的资源浪费。

在TypeScript中,我们主要通过Promise和async/await进行一步编程,后者是前者的简化语法糖,具体内容我们在对应模块中进行详细介绍;

2.网络请求

在当下主流 Web 应用开发中,网络请求是获取和发送数据的重要手段。无论是从服务器获取数据,还是向服务器提交表单,网络请求都是不可或缺的。

在 TypeScript 中,常用的网络请求方法包括 XHRfetchaxios。它们的本质都是通过 HTTP 协议与服务器进行通信。fetchaxios 都基于 Promise,支持异步操作,使得我们可以使用 async/await 来简化异步代码的编写。

下面作者将两个模块分别进行描述!😘


一. TypeScript 中的异步编程模块

1.TypeScript 编译器与 ES5 标准

① TypeScript 默认使用 ES5 标准

TypeScript 是一种强类型的 JavaScript 超集,它通过编译器将 TypeScript 代码转换为 JavaScript 代码。默认情况下,TypeScript 编译器会将代码编译为 ES5 标准,以确保生成的 JavaScript 代码在大多数现代浏览器中都能正常运行。

② 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();

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();
②串行执行多个异步操作

在某些场景下,我们需要按顺序执行多个异步操作,例如预先加载多个数据。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();

这里我们定义了两个异步函数 asyncOperation1asyncOperation2,它们分别返回一个 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();

二、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));

这里我们分析一下这个过程:

② 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 的请求流程
  1. 创建请求:使用 axios 函数创建一个请求。
  2. 发送请求axios 函数会发送请求到指定的 URL。
  3. 接收响应:服务器返回响应后,axios 函数会返回一个包含响应数据的 Promise。
  4. 处理响应:通过 .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)。
  • 请求日志记录:记录请求的详细信息,便于调试和监控。
  • 请求重试:在请求失败时自动重试。

代码如下:

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));

请求拦截器就讲到这里,更多应用还是得实践尝试!

② 响应拦截器

响应拦截器允许我们在响应返回后对响应数据进行处理或添加额外的逻辑。常见的使用场景包括:

  • 统一处理响应数据:对响应数据进行格式化或解密。
  • 错误处理:统一处理服务器返回的错误信息。
  • 响应日志记录:记录响应的详细信息,便于调试和监控。
  • 权限校验:在响应中检查用户权限,并根据权限进行相应的操作。

下面是个代码案例:

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));

三、案例实践

这里作者基于实现一个全栈案例Demo,下面是技术栈:

  • 前端:Vue3 +TypeScript
  • 后端:FastAPI + Python
  • 网络请求:Axios

1 环境搭建

① 项目创建

Vite 是一个现代化的前端构建工具,它提供了快速的开发体验。我们可以使用 Vite 快速创建一个 Vue 3 + TypeScript 项目。

  1. 安装 Vite
npm install -g create-vite
  1. 创建vite项目
npm create vite
  1. 选择项目模板

  1. 选择 TypeScript 支持

  1. 进入项目目录并安装依赖

② 项目启动

安装完依赖后,可以使用以下命令启动开发服务器:

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>

当然我们这里成功加载了一些公共服务的API,我们也可以自己搭建后端获取数据,下面我们简单介绍一下使用Python语言基于FastAPI框架进行后端搭建的Demo;

4. 使用 FastAPI 搭建后端服务

① 安装和配置 FastAPI

FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API。我们可以使用 FastAPI 快速搭建一个后端服务。

  1. 安装 FastAPI 和 Uvicorn
pip install fastapi uvicorn
  1. 创建一个简单的 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}
  1. 启动 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>

经过测试,获取成功!!

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;
}
④ 封装请求方法

创建一个 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;
};
⑤ 在组件中使用封装的 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>

⑥ 使用 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);
    }
  },
}

Over,作者的总结完毕!😘👌😊 本次学习总结到此结束!!🙂 各位读者可以参考本文通过代码实践来加深理解!😉

相关链接

  • 项目地址:TypeScript-CookBook
  • 相关文档:专栏地址
  • 作者主页:GISer Liu-CSDN博客

thank_watch

举报

相关推荐

0 条评论