Vue 与服务器通信

引言

在构建数据驱动的 Vue 应用时,与服务器的通信是核心功能之一。本文将深入介绍如何在 Vue 中使用 axios 与服务器 API 交互,并展示如何封装 API 调用、错误处理和加载状态管理,以及如何将 API 接口统一管理以提高代码的可维护性和复用性。

本章知识点:

  • 使用 axios 与服务器 API 交互
  • 处理 HTTP 请求和响应
  • 管理 API 错误和加载状态
  • 封装 HTTP 服务和使用服务工作器

回顾

在之前的章节中,我们学习了 Vue 的基础知识、组件化开发、状态管理、动画与过渡等。现在,我们将转向 Vue 与服务器通信的高级话题。

使用 axios 与服务器 API 交互

Axios 是一个基于 promise 网络请求库,作用于node.js浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和 node.js 中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests, 广泛用于 Vue 应用中,以实现与服务器的异步通信

Axios 特性:

  • 从浏览器创建 XMLHttpRequests

  • 从 node.js 创建 http 请求

  • 支持 Promise API

  • 拦截请求和响应

  • 转换请求和响应数据

  • 取消请求

  • 超时处理

  • 查询参数序列化支持嵌套项处理

  • 自动将请求体
    序列化
    为:

    • JSON (application/json)
    • Multipart / FormData (multipart/form-data)
    • URL encoded form (application/x-www-form-urlencoded)
  • 将 HTML Form 转换成 JSON 进行请求

  • 自动转换 JSON 数据

  • 获取浏览器和 node.js 的请求进度,并提供额外的信息(速度、剩余时间)

  • 为 node.js 设置带宽限制

  • 兼容符合规范的 FormData 和 Blob(包括 node.js)

  • 客户端支持防御 XSRF

安装 axios

首先,确保安装了 axios 库:

bash

复制代码npm install axios

发起 HTTP 请求

使用 axios 发起 GET 和 POST 请求:

javascript复制代码// GET请求
axios
  .get("https://api.baidu.com/data")
  .then((response) => {
    console.log(response.data);
  })
  .catch((error) => {
    console.error("出错:", error);
  });

// POST请求
axios
  .post("https://api.baidu.com/data", { key: "value" })
  .then((response) => {
    console.log(response.data);
  })
  .catch((error) => {
    console.error("出错:", error);
  });

请求和响应拦截器

通过拦截器,我们可以统一处理请求前的配置和响应后的数据。

实例演示

javascript复制代码import axios from "axios";
const instance = axios.create({
  baseURL: "https://api.baidu.com",
  timeout: 1000, //设置接口请求超时时间
});

instance.interceptors.request.use(
  (config) => {
    // 在发送请求之前做些什么
    return config;
  },
  (error) => {
    // 对请求错误做些什么
    return Promise.reject(error);
  }
);

instance.interceptors.response.use(
  (response) => {
    // 对响应数据做点什么
    return response;
  },
  (error) => {
    // 对响应错误做点什么
    return Promise.reject(error);
  }
);

管理 API 错误和加载状态

有效的错误处理和加载状态管理能够提升用户体验。

错误处理

集中管理 API 错误,例如创建一个错误处理服务。

加载状态

使用 Vue 的响应式系统来管理加载状态。

实例演示

javascript复制代码// 在Vue组件中管理加载状态和错误
data() {
  return {
    isLoading: false,
    error: null
  };
},
methods: {
  async fetchData() {
    this.isLoading = true;
    try {
      const response = await http.get('/data');
      // 处理数据
    } catch (error) {
      this.error = error;
      console.error('请求出错:', error);
    } finally {
      this.isLoading = false;
    }
  }
}

封装 HTTP 服务

封装 HTTP 服务是提高代码复用性和简化 API 调用的关键步骤。

创建 HTTP 服务模块

javascript复制代码// httpService.js
import axios from "axios";

// 创建axios实例
const instance = axios.create({
  baseURL: "https://api.baidu.com",
  timeout: 1000, //设置接口请求超时时间
  headers: { "X-Custom-Header": "foobar" },
});

// 请求拦截器
instance.interceptors.request.use(
  (config) => {
    config.headers["Authorization"] = `Bearer ${localStorage.getItem("token")}`;
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 响应拦截器
instance.interceptors.response.use(
  (response) => {
    return response;
  },
  (error) => {
    if (error.response && error.response.status === 401) {
      // 处理未授权错误
      console.log("未认证。。:", error.response.data);
    }
    return Promise.reject(error);
  }
);

export default instance;

API 接口封装层

将后端 API 接口统一管理,可以方便其他文件复用。

创建 API 接口文件

javascript复制代码// api.js
// 获取用户
export const fetchData = () => httpService.get("/users");
// 创建用户
export const createUser = (userData) => httpService.post("/users", userData);
// 更新用户
export const updateUser = (userId, userData) =>
  httpService.put(`/users/${userId}`, userData);
// 删除用户
export const deleteUser = (userId) => httpService.delete(`/users/${userId}`);

在 Vue 组件中使用封装的 API

javascript复制代码// UserList.vue
import { fetchData } from "./api";

export default {
  data() {
    return {
      users: [],
      isLoading: false,
      error: null,
    };
  },
  methods: {
    async loadUsers() {
      this.isLoading = true;
      try {
        const response = await fetchData();
        this.users = response.data;
      } catch (error) {
        this.error = error;
        console.error("请求用户出错:", error);
      } finally {
        this.isLoading = false;
      }
    },
  },
  mounted() {
    this.loadUsers();
  },
};

请求取消

Axios 提供了两种主要的方法来取消请求,分别是使用 CancelTokenAbortController

以下是这两种方法的基本用法:

  1. 使用 AbortController
  • Axios 支持使用 AbortController 来取消请求,这是一种与 fetch API 类似的取消方式。
  • 创建一个 AbortController 实例,并将其 signal 属性传递给 Axios 请求的 signal 配置项。
  • 调用 abort 方法来取消请求。

javascript复制代码const controller = new AbortController(); // 创建 AbortController 实例

axios
.get(“/foo/bar”, {
signal: controller.signal, // 将 signal 传递给请求
})
.then(function (response) {
// 请求成功处理
})
.catch(function (error) {
// 请求失败处理
});

// 取消请求
controller.abort();

  1. 使用 CancelToken(官方已经弃用了)
  • 首先,你需要创建一个取消标记(cancel token)。
  • 然后,将这个标记与特定的请求关联。
  • 当需要取消请求时,调用标记中的 cancel 方法。

javascript复制代码import axios from “axios”;

const source = axios.CancelToken.source(); // 创建取消标记

axios
.get(“/api/data”, {
cancelToken: source.token, // 将取消标记与请求关联
})
.then((response) => {
// 请求成功处理
})
.catch((error) => {
if (axios.isCancel(error)) {
console.log(“请求被取消”, error.message);
} else {
console.log(“请求出错”, error.message);
}
});

// 取消请求
source.cancel(“请求取消的原因”);

Axios 与 Fetch 特性对比

特性/功能AxiosFetch
定义Axios 是一个基于 promise 的 HTTP 客户端Fetch 是浏览器提供的 API,用于发起网络请求
浏览器兼容性需要安装 Axios 库无需额外安装,现代浏览器内置支持
Promise基于 Promise,易于使用 async/await返回 Promise 对象,也支持 async/await
拦截器支持请求和响应拦截器不内置拦截器,需要手动实现
取消请求支持请求取消,使用 CancelToken 或 AbortController支持请求取消,使用 AbortController
请求配置支持全局和局部配置配置较为简单,主要通过 options 对象
错误处理错误处理较为简单,统一捕获需要手动检查响应状态和处理异常
超时控制支持请求超时设置不内置超时控制,需要手动实现
JSON 处理自动处理 JSON 数据的请求和响应需要手动处理 JSON 数据的转换
类型支持TypeScript 友好TypeScript 支持,但需要额外配置
测试易于测试和模拟测试和模拟较为复杂,需要额外工具
社区和文档活跃的社区,丰富的文档和插件标准 API,文档较为官方和简洁
使用场景适用于复杂的 HTTP 请求处理适用于简单的 HTTP 请求或需要浏览器兼容性的场景

共同点:

  • 两者都基于 Promise,支持 async/await。
  • 两者都支持请求取消。
  • 两者都可以处理 JSON 数据。

差异:

  • Axios 是一个第三方库,需要安装,而 Fetch 是浏览器内置的 API。
  • Axios 提供了更丰富的功能,如拦截器、请求配置、错误处理等。
  • Axios 对 TypeScript 更友好,而 Fetch 需要额外配置 TypeScript。
  • Axios 的错误处理和超时控制更为简单和直观。
  • Fetch 的配置和使用相对简单,但需要手动处理一些功能,如拦截器和超时控制。

fetch 使用示例

基本语法

javascript复制代码fetch(url, options)
  .then((response) => {
    // 处理响应
    if (!response.ok) {
      throw new Error("网络响应出错");
    }
    return response.json(); // 假设响应是 JSON 格式
  })
  .then((data) => console.log(data))
  .catch((error) => console.error("请求出错:", error));

参数说明

  • url: 请求的 URL。

  • options
    可选参数,可以包含以下属性:
    • method: 请求方法,例如 GETPOSTPUTDELETE 等。
    • headers: 请求头对象。
    • body: 请求体,对于 GETHEAD 请求,这个属性会被忽略。
    • mode: 请求模式,例如 corsno-corssame-origin
    • credentials: 凭证类型,例如 includesame-originomit
    • cache: 缓存模式,例如 defaultno-cachereloadforce-cache
    • redirect: 重定向模式,例如 followerrormanual
    • referrer: 引用页 URL。
    • integrity: 子资源完整性校验值。

fetch 的高级配置

  • 请求发送:通过fetch API 来发起网络请求
  • 请求超时:通过设置一个超时计时器,并在超时时使用 AbortController 取消请求。
  • 取消请求:通过 AbortController 实现请求的取消。
  • JSON 处理:手动调用 .json() 方法来解析响应体中的 JSON 数据。
  • 错误处理:通过 .catch() 捕获请求过程中的错误,并手动处理不同类型的错误。
  • 请求配置:通过 requestOptions 对象来配置请求方法、头部等信息。
javascript复制代码// 1. 定义 fetch 请求函数
function fetchData(url, options = {}) {
  const controller = new AbortController(); // 支持取消请求
  const signal = controller.signal;

  // 设置请求超时,需要手动实现
  const timeoutId = setTimeout(() => controller.abort(), 5000); // 5秒超时

  // 配置请求选项
  const fetchOptions = {
    ...options, // 允许传入自定义配置
    signal, // 将 AbortController 的 signal 绑定到请求
  };

  // 发起 fetch 请求
  return fetch(url, fetchOptions)
    .then((response) => {
      if (!response.ok) {
        // 需要手动检查响应状态
        throw new Error("网络响应出错");
      }
      return response.json(); // 手动处理 JSON 数据转换
    })
    .catch((error) => {
      if (error.name === "AbortError") {
        console.error("请求中止:", error.message);
      } else {
        console.error("请求出错:", error);
      }
      throw error; // 需要手动处理异常
    });
}

// 2. 使用 fetch 请求函数
const url = "https://api.baidu.com/data";

// 配置请求选项,例如设置请求头
const requestOptions = {
  method: "GET",
  headers: {
    "Content-Type": "application/json",
  },
};

fetchData(url, requestOptions)
  .then((data) => console.log("接收的数据:", data))
  .catch((error) => console.error("请求出错:", error));

// 3. 取消请求
// 在某个条件下取消请求,例如用户点击取消按钮
setTimeout(() => {
  console.log("取消请求...");
  // 调用 AbortController 的 abort 方法取消请求
  clearTimeout(timeoutId); // 清除超时
  controller.abort("用户取消 "); // 取消请求
}, 3000); // 假设在3秒后取消请求

结语

通过本站的学习,我们掌握了如何在 Vue 中使用 axios 与服务器 API 进行交互,封装 HTTP 服务,处理 HTTP 请求和响应,以及管理 API 错误和加载状态,fetch 的探索。此外,我们还学习了如何将 API 接口统一管理,以提高代码的可维护性和复用性。

互动交流

欢迎在文章下方留言,分享学习 Vue 与服务器通信的心得体会,或提出在使用过程中遇到的问题。我们将在后续的文章中提供解答和指导。

  • 23
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值