后台经验系列(一)--网络封装(上)


theme: orange

导读

这一系列文章记录了我在多年工作中积累的一些心得,目的是为了分享经验,并欢迎各位大佬指教,以便提升我的技术水平。

在工作中,我们经常需要与后端对接,通过接口进行数据传输,常用的网络请求库包括axios、ajax、fetch等。那么,如何对这些库进行二次封装,以便更好地完成我们的业务开发呢?

一、为什么要进行封装

刚学习编程的新人可能会有疑问,为什么很多教程都介绍了封装网络请求的必要性?根据我的工作经验,封装网络请求主要有以下三个目的:

按照我的工作经验,封装的目的,主要是为了三个目的:

  1. 区分技术代码和业务代码。将技术代码独立封装,对外提供接口供业务代码调用。这样即使新人不了解底层原理,也可以快速上手,提升开发效率,并实现理想的效果。
  2. 方便版本升级。例如,一个老项目使用了 echarts V3,但新需求要求使用的特性只有最新版 V5 有。如果直接升级依赖,可能会导致旧代码崩溃。而通过封装,只需修改封装部分的依赖,确保兼容性即可。
  3. 添加新特性。在原有功能的基础上,添加适配项目需求的特性。接下来的内容将介绍如何实现这些封装。

此文章讲解的是网络的封装,我就拿ajax来举例,将大家一步一步封装成我们自己希望的效果。因为ajax够简单

二、ajax的直接使用

$.ajax({
  url: 'http://localhost:8080/ok',
  type: 'get',
  success: function (res) {
    console.log(res); // 请求成功返回数据
  },
  error: function (err) {
    console.log(err); // 请求失败返回数据
  },
});

以上是 ajax 的基本使用,虽然简单,但存在诸多问题:

  1. 使用回调函数处理请求,多个请求时会形成回调地狱,可读性差。不清楚这个名词的,可以自己去搜一下。
  2. 环境没有区分,如开发、测试、正式环境的 URL 不同。如果 URL 写死,上线测试和正式环境时会有很多问题
  3. ......

这些缺点还有很多,我们先封装一个简单的函数,解决这两个问题,再继续深入。

三、 ajax的初步封装

1. 去除回调函数,改用 Promise

新建一个 request 文件夹,然后在其中新建一个 index.js 文件,作为网络封装的入口文件:

// src/utils/request/index.js
/**
 * 执行AJAX请求
 * @param {string} url 请求的URL
 * @param {string} type 请求类型(如GET、POST等)
 * @param {Object|string} data 要发送的数据
 * @returns {Promise} 返回一个Promise对象,成功时resolve响应结果,失败时reject错误对象
 */
export function ajaxFunc({ url, type='get', data }) {
  // 创建一个新的Promise,通过$.ajax来处理异步请求
  return new Promise((resolve, reject) => {
    $.ajax({
      url,
      type,
      data,
      // 请求成功时调用的回调函数
      success: function (res) {
        resolve(res);
      },
      // 请求失败时调用的回调函数
      error: function (err) {
        reject(err);
      },
    });
  });
}

以上代码封装了一个函数,将 ajax 包裹在 Promise 中,使我们在使用时可以利用 async/await 解决回调地狱问题:

import { ajaxFunc } from '@/utils/request/index.js'
async function demo() {
  try {
    const res = await ajaxFunc({
      url: 'http://localhost:8080/ok',
      type: 'get',
    });
    console.log(res);
  } catch (error) {
    console.log(error);
  }
}

然以上代码看起来不如直接使用简单,但在处理多个依赖顺序的请求时,差别就显而易见了。

2. 引入环境变量

我们可以引入一个变量 baseUrl,将基础 URL 放在其中,这样只需修改这个变量即可切换环境:

// src/utils/request/index.js

// 开发环境
const baseUrl = ‘http://localhost:8080’;

/**

  • 执行AJAX请求
  • @param {string} url 请求的URL
  • @param {string} type 请求类型(如GET、POST等)
  • @param {Object|string} data 要发送的数据
  • @returns {Promise} 返回一个Promise对象,成功时resolve响应结果,失败时reject错误对象
    */
    function ajaxFunc({ url, type = ‘get’, data }) {
    const realUrl = baseUrl + url;
    // 创建一个新的Promise,通过$.ajax来处理异步请求
    return new Promise((resolve, reject) => {
    $.ajax({
    url: realUrl,
    type,
    data,
    // 请求成功时调用的回调函数
    success: function (res) {
    resolve(res);
    },
    // 请求失败时调用的回调函数
    error: function (err) {
    reject(err);
    },
    });
    });
    }

在使用时,去掉前面的 IP:

import { ajaxFunc } from '@/utils/request/index.js'
async function demo() {
  try {
    const res = await ajaxFunc({
      url: '/ok',
      type: 'get',
    });
    console.log(res);
  } catch (error) {
    console.log(error);
  }
}

这样,一个最简单的 ajax 封装就完成了,对于一些小项目来说已经足够。但对于大型项目,这还远远不够。下一篇文章将介绍如何在代码中处理请求错误、携带 token、取消重复请求、处理文件流等,使功能更加丰富。


这是一个从 https://juejin.cn/post/7368656101074927656 下的原始话题分离的讨论话题