前端接口请求——常用的一些总结

第一阶段:ajax

早在2005年之前,传统的网页更新内容,是同步的,需要重新加载整个网页,但是这个过程需要用户等待。在 2005 年,Google 通过其 Google Suggest 使 AJAX 变得流行起来。可以不必刷新整个页面,而只是更新部分内容,表"Asynchronous JavaScript and XML"(异步JavaScript和XML)。ajax可以在前端和后台通信时,不阻塞用户对于网页的操作。

原因:

  1. 获取网页资源需要向后端发送请求,加载网页资源
  2. 通过js事件触发,可以局部更新网页信息,js触发,浏览器发送网络请求,通过 XMLHttpRequest方法发送异步的ajax请求,获取信息,局部的刷新页面

ajax的发展关键点:

  • XMLHttpRequest的诞生(1998年):
    • Microsoft在Internet Explorer 5中首次引入了XMLHttpRequest对象,这是AJAX技术的基础。它允许浏览器在不刷新页面的情况下与服务器进行数据交换
  • AJAX术语的提出(2005年):
    • Jesse James Garrett在Adaptive Path公司提出了AJAX这个术语,并在一篇名为"Ajax: A New Approach to Web Applications"的文章中对其进行了描述。这篇文章迅速传播,提高了人们对AJAX技术的认识。
  • Google的推动(2005年-2006年):
    • Google推出了基于AJAX的Web应用,如Gmail和Google Maps,这些应用展示了AJAX技术的强大潜力,促进了AJAX技术的广泛采用。
  • JavaScript库和框架的支持:
    • jQuery(2006年)等JavaScript库开始提供对AJAX的支持,简化了AJAX的实现过程。这些库通过封装AJAX请求,使得开发者可以更容易地实现异步数据交互。
  • Fetch API的引入(2015年):
    • Fetch API作为原生的Web API被引入,提供了一种更现代、更简洁的方式来进行网络请求。它逐渐成为AJAX的替代者,尤其是在现代浏览器中。
  • 现代前端框架的集成
    • React、Angular和Vue.js等现代前端框架内置了对AJAX或Fetch API的支持,使得开发者可以更容易地实现复杂的异步数据交互。
  • 服务端渲染(SSR)和静态站点生成(SSG)的兴起:
    • 随着Web技术的发展,服务端渲染和静态站点生成等技术开始流行,这些技术在某些场景下提供了比AJAX更优的解决方案,尤其是在性能和SEO方面。

AJAX的发展不仅推动了Web应用从静态页面向动态、交互式应用的转变,而且也催生了一系列新的开发模式和最佳实践。尽管现代Web开发中出现了新的技术和方法,但AJAX仍然是实现异步数据交互的重要技术之一。

1. 原生js的基本实现

针对get请求:

js 复制代码
var xhr = new XMLHttpRequest();

xhr.open('GET', 'https://api.example.com/data', true);

xhr.onload = function() {
  if (xhr.status >= 200 && xhr.status < 300) {
    // 请求成功
    console.log(xhr.responseText);
  } else {
    // 请求失败
    console.error('Request failed with status:', xhr.status);
  }
};

xhr.onerror = function() {
  // 网络或请求错误
  console.error('Network or request error.');
};

xhr.send();

针对post请求

js 复制代码
var xhr = new XMLHttpRequest();

xhr.open('POST', 'https://api.example.com/data', true);
xhr.setRequestHeader('Content-Type', 'application/json');

var data = JSON.stringify({ key1: 'value1', key2: 'value2' });
xhr.send(data);

xhr.onload = function() {
  if (xhr.status >= 200 && xhr.status < 300) {
    // 请求成功
    console.log(xhr.responseText);
  } else {
    // 请求失败
    console.error('Request failed with status:', xhr.status);
  }
};

xhr.onerror = function() {
  // 网络或请求错误
  console.error('Network or request error.');
};

readyState变化时: XMLHttpRequest 对象的 readyState 属性表示请求的状态,它是一个从 0 到 4 的整数。每个 readyState 值对应一个特定的状态:

  1. XMLHttpRequest.UNSENT (0):请求未初始化,open() 方法尚未调用,或者已经调用,但没有调用 send() 方法。
  2. XMLHttpRequest.OPENED (1):open() 方法已调用,请求已准备就绪,可以发送。
  3. XMLHttpRequest.HEADERS_RECEIVED (2):服务器已接收到请求的 headers,onheaders 事件已经处理完毕。
  4. XMLHttpRequest.LOADING (3):请求正在接收数据。在这个阶段,responseTextresponseXML 属性可能会部分更新,但直到 readyState 变为 4,这些属性才是完整的。
  5. XMLHttpRequest.DONE (4):请求已完成。此时,服务器已经处理完毕请求,并且响应是最终的。如果 status 属性的值在 200 到 299 之间,说明请求成功;否则,请求失败。
js 复制代码
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
  if (xhr.readyState === XMLHttpRequest.DONE) {
    if (xhr.status === 200) {
      // 请求成功,处理响应
      console.log(xhr.responseText);
    } else {
      // 请求失败,处理错误
      console.error('Request failed with status:', xhr.status);
    }
  }
  // 其他状态可以在这里处理,如果需要的话
};
xhr.open('GET', 'https://api.example.com/data');
xhr.send();

2. promise封装

js 复制代码
function ajaxPromise(method, url, data, headers) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();

    // 设置请求方法和 URL
    xhr.open(method.toUpperCase(), url, true);

    // 设置请求头(如果提供了数据,对于 POST 请求)
    if (data && method.toUpperCase() === 'POST') {
      xhr.setRequestHeader('Content-Type', 'application/json');
    }
    if (headers) {
      Object.keys(headers).forEach((header) => {
        xhr.setRequestHeader(header, headers[header]);
      });
    }

    // 定义响应处理函数
    xhr.onload = function() {
      if (xhr.status >= 200 && xhr.status < 300) {
        // 请求成功
        resolve(xhr.response || xhr.responseText);
      } else {
        // 请求失败
        reject(new Error(`Request failed with status ${xhr.status}`));
      }
    };

    // 定义错误处理函数
    xhr.onerror = function() {
      reject(new Error('Network error'));
    };

    // 发送请求
    xhr.send(data);
  });
}

// 使用示例
ajaxPromise('GET', 'https://api.example.com/data')
  .then(response => {
    console.log('Response:', response);
  })
  .catch(error => {
    console.error('Error:', error);
  });

// 发送 POST 请求
ajaxPromise('POST', 'https://api.example.com/data', { key: 'value' }, { 'Authorization': 'Bearer your_token' })
  .then(response => {
    console.log('Response:', response);
  })
  .catch(error => {
    console.error('Error:', error);
  });

在这个封装的 ajaxPromise 函数中,我们处理了以下功能:

  1. 请求拦截

    • 通过设置请求头,你可以传递认证令牌或其他自定义头信息。
  2. 响应处理

    • 当请求成功时(HTTP 状态码在 200 到 299 之间),resolve 函数会被调用,返回响应数据。
    • 如果请求失败(HTTP 状态码不在 200-299 之间),reject 函数会被调用,返回错误信息。
  3. 错误处理

    • 如果请求过程中发生网络错误,onerror 事件处理器会被触发,reject 函数会被调用,返回错误信息。
  4. 跨域支持

    • 请注意,跨域资源共享(CORS)需要服务器端设置适当的响应头。这个封装的函数不会改变服务器端的 CORS 策略,但它会正确处理浏览器的 CORS 策略。
  5. 数据格式

    • 对于 POST 请求,如果提供了数据,函数会自动将数据序列化为 JSON 字符串,并设置请求头为 application/json

第二阶段:利用jQuery实现ajax方法

jQuery 提供了一个简化的 AJAX API,使得发送 HTTP 请求变得更加容易。以下是如何使用 jQuery 实现 AJAX 请求的基本步骤:

  1. 引入 jQuery 库: 在你的 HTML 文件中,确保引入了 jQuery 库。你可以从 jQuery 官网获取最新版本的库,或者使用 CDN。

    html 复制代码
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  2. 编写 AJAX 请求代码 : 使用 $.ajax 方法来发送请求。这个方法接受一个配置对象,你可以在这个对象中设置请求的类型、URL、数据、请求头等。

    javascript 复制代码
    $.ajax({
      url: 'https://api.example.com/data', // 请求的 URL
      type: 'GET', // 请求类型,可以是 'GET', 'POST', 'PUT', 'DELETE' 等
      dataType: 'json', // 预期服务器返回的数据类型
      data: { key1: 'value1', key2: 'value2' }, // 发送到服务器的数据(对于 GET 请求,这些数据将被添加到 URL 中)
      headers: {
        'Authorization': 'Bearer your_token' // 自定义请求头
      },
      success: function(response) {
        // 请求成功时的回调函数,response 包含服务器返回的数据
        console.log(response);
      },
      error: function(jqXHR, textStatus, errorThrown) {
        // 请求失败时的回调函数
        console.error(textStatus, errorThrown);
      }
    });
  3. 处理响应 : 在 success 回调函数中,你可以处理服务器返回的数据。如果请求失败,你可以在 error 回调函数中处理错误。

  4. 链式调用: 如果你需要在 AJAX 请求完成后执行其他操作,你可以使用 jQuery 的链式调用。

    javascript 复制代码
    $.ajax({
      // ... AJAX 设置
    }).done(function(response) {
      // 请求成功,可以在这里更新页面内容
      $('#data-container').html(response.html);
    }).fail(function(jqXHR, textStatus, errorThrown) {
      // 请求失败,可以在这里显示错误信息
      $('#error-container').text('Error: ' + textStatus);
    });
  5. 使用 $.get$.post 方法: 对于简单的 GET 和 POST 请求,jQuery 提供了更简洁的方法。

    javascript 复制代码
    // GET 请求
    $.get('https://api.example.com/data', function(data) {
      console.log(data);
    });
    
    // POST 请求
    $.post('https://api.example.com/data', { key1: 'value1', key2: 'value2' }, function(data) {
      console.log(data);
    }).fail(function(jqXHR, textStatus, errorThrown) {
      console.error(textStatus, errorThrown);
    });

第三阶段:axios

javascript 复制代码
Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js 环境。
它具有许多特性,包括拦截请求和响应、转换请求和响应数据、取消请求、自动转换 JSON 数据等。
以下是 Axios 的一些关键知识点和如何使用它发送网络请求的示例。
Axios 知识点:
  1. 基于 Promise: Axios 完全基于 Promise,这使得异步处理更加简洁和易于理解。

  2. 拦截器: 你可以使用 Axios 的拦截器来拦截请求或响应。这对于添加认证头、处理错误等场景非常有用。

  3. 请求和响应的类型转换: Axios 允许你指定期望从服务器接收的数据类型(如 JSON、XML、HTML 等),并自动转换响应数据。

  4. 配置: Axios 提供了丰富的配置选项,允许你定制请求的行为,如设置超时、配置代理、添加全局请求头等。

  5. 取消功能: Axios 支持取消请求,这对于防止不必要的请求(如用户导航离开当前页面)非常有用。

如何使用 Axios 发送网络请求:

发送 GET 请求

javascript 复制代码
axios.get('https://api.example.com/data')
  .then(function (response) {
    // 请求成功,处理响应数据
    console.log(response.data);
  })
  .catch(function (error) {
    // 请求失败,处理错误
    console.error('Error:', error);
  });

发送 POST 请求

javascript 复制代码
axios.post('https://api.example.com/data', {
  key1: 'value1',
  key2: 'value2'
})
  .then(function (response) {
    // 请求成功,处理响应数据
    console.log(response.data);
  })
  .catch(function (error) {
    // 请求失败,处理错误
    console.error('Error:', error);
  });

使用拦截器

javascript 复制代码
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
  // 在发送请求之前可以做些什么
  config.headers.Authorization = 'Bearer ' + getToken(); // 例如,添加认证头
  return config;
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error);
});

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
  // 对响应数据做点什么
  return response;
}, function (error) {
  // 对响应错误做点什么
  return Promise.reject(error);
});

取消请求

javascript 复制代码
// 创建取消令牌
const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.get('https://api.example.com/data', {
  cancelToken: source.token
})
  .then(function (response) {
    // 请求成功
  })
  .catch(function (thrown) {
    if (axios.isCancel(thrown)) {
      // 请求被取消
      console.log('Request canceled', thrown.message);
    } else {
      // 处理其他错误
    }
  });

// 取消请求
source.cancel('Operation canceled by the user.');

v0.22.0 开始,Axios 支持以 fetch API 方式------ AbortController 取消请求:

js 复制代码
const controller = new AbortController();

axios.get('/foo/bar', {
   signal: controller.signal
}).then(function(response) {
   //...
});
// 取消请求
controller.abort()
sql 复制代码
这些示例展示了 Axios 的基本用法,包括发送 GET 和 POST 请求、使用拦截器以及取消请求。
Axios 的这些特性使其成为处理 HTTP 请求的强大工具,无论是在构建简单的前端应用还是复杂的后端服务时都非常有用。

一个项目中会包含多个接口请求,为了具体的业务需求和减少重复代码,都会对axios进行封装,封装的方式如下所示:

封装的好处

  • 统一处理请求和响应:统一处理http请求
  • 简化api的调用:每个api接口创建一个函数即可
  • 提高代码的可维护性

对于大型项目,确实需要对 Axios 进行封装以满足特定的业务需求、减少代码重复,并提供统一的请求处理机制。以下是一个基本的 Axios 封装示例,它包括了请求队列管理、请求取消、统一的错误处理和配置等:

javascript 复制代码
import axios from 'axios';
import qs from 'qs';

// 创建 Axios 实例
const service = axios.create({
  baseURL: process.env.VUE_APP_API_BASE_URL, // 基础 URL,根据环境变量配置
  timeout: 5000, // 请求超时时间
  headers: {
    'Content-Type': 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded'
  }
});

// 请求拦截器
service.interceptors.request.use(
  config => {
    // 在发送请求之前可以做些什么
    if (config.method === 'post' || config.method === 'put') {
      config.data = qs.stringify(config.data); // 序列化表单数据
    }
    return config;
  },
  error => {
    // 请求错误处理
    console.error('Request Error:', error);
    return Promise.reject(error);
  }
);

// 响应拦截器
service.interceptors.response.use(
  response => {
    const res = response.data;
    // 对响应数据做点什么
    if (res.code !== 200) {
      // 处理错误情况,例如显示错误消息或跳转到错误页面
      // 可以根据实际情况决定是否抛出错误
      return Promise.reject(new Error(res.message || 'Error'));
    } else {
      return res;
    }
  },
  error => {
    // 响应错误处理
    console.error('Response Error:', error);
    return Promise.reject(error);
  }
);

// 封装请求方法
const request = {
  get: (url, params) => service.get(url, { params }),
  post: (url, data) => service.post(url, data),
  put: (url, data) => service.put(url, data),
  delete: (url) => service.delete(url),
  patch: (url, data) => service.patch(url, data),
};

// 取消请求的方法
const cancel = (source) => {
  source.cancel('Operation canceled by the user.');
};

export { request, cancel };

在这个封装中,我们首先创建了一个 Axios 实例 service,并设置了基础 URL 和请求超时时间。我们还设置了请求拦截器和响应拦截器,用于序列化请求数据和处理响应数据。

然后,我们封装了一组请求方法 getpostputdeletepatch,这些方法可以直接用于发起不同类型的 HTTP 请求。

最后,我们提供了一个 cancel 方法,用于取消正在进行的请求。

在项目中使用封装的 Axios 方法:

javascript 复制代码
import { request, cancel } from './api';

// 发起 GET 请求
request.get('/api/data', { param: 'value' })
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error(error);
  });

// 发起 POST 请求
request.post('/api/data', { key: 'value' })
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error(error);
  });

// 取消请求
const source = axios.CancelToken.source();
request.get('/api/data', { cancelToken: source.token })
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    if (axios.isCancel(error)) {
      console.log('Request canceled');
    } else {
      console.error(error);
    }
  });

// 取消之前的请求
cancel(source);

这个封装提供了一个简洁的 API,使得在项目中发起请求变得更加方便和一致。同时,通过拦截器和错误处理,我们可以确保请求的一致性和错误处理的统一性。

第四阶段:fetch请求

fetch 是一个现代的、原生的 JavaScript API,用于发起网络请求。它提供了一种简洁、强大的方式来处理 HTTP 请求和响应。以下是如何使用 fetch API 发起网络请求的基本步骤和示例:

基本步骤:

  1. 调用 fetch 函数 : 使用 fetch 函数并传入请求的 URL 和可选的配置对象。

  2. 配置请求(可选): 在配置对象中,你可以指定请求方法(如 'GET', 'POST', 'PUT', 'DELETE' 等)、请求头、请求体等。

  3. 处理响应fetch 函数返回一个 Promise 对象,它在请求成功时解析为 Response 对象。你可以使用 .then() 方法来处理这个 Response 对象。

  4. 从响应中获取数据 : 使用 Response 对象的 .json().text().blob() 方法来解析响应数据。

  5. 错误处理 : 使用 .catch() 方法来捕获和处理请求过程中发生的错误。

示例代码:

发送 GET 请求

javascript 复制代码
fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json(); // 解析 JSON 数据
  })
  .then(data => {
    console.log(data); // 处理请求到的数据
  })
  .catch(error => {
    console.error('Fetching failed:', error); // 处理错误
  });

发送 POST 请求

javascript 复制代码
fetch('https://api.example.com/data', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ key1: 'value1', key2: 'value2' }) // 设置请求体
})
.then(response => response.json())
.then(data => {
  console.log(data); // 处理请求到的数据
})
.catch(error => {
  console.error('Posting failed:', error); // 处理错误
});

处理跨域问题

如果你遇到跨域问题(CORS),你需要确保服务器端设置了正确的 CORS 策略。浏览器会自动处理跨域资源共享(CORS)的预检请求(preflight request),如果服务器允许跨域请求,浏览器将执行实际的请求。

使用 async/await 简化代码

使用 async 函数和 await 关键字可以让异步代码看起来更像同步代码,从而简化错误处理和流程控制。

javascript 复制代码
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();
    console.log(data); // 处理请求到的数据
  } catch (error) {
    console.error('Error:', error); // 处理错误
  }
}

fetchData();

fetch和xhr的区别:

fetch API 提供了一个现代的方式来发起网络请求,它已经成为现代浏览器中的标准部分。然而,如果你需要支持旧浏览器,可能需要使用 XMLHttpRequest 或引入一个 fetch 的 polyfill。 fetch API 相比于 XMLHttpRequest(XHR)具有以下几个主要优势:

  1. Promise 支持fetch 返回一个 Promise 对象,这使得异步操作更加简洁和易于管理。你可以使用 .then().catch() 方法来处理成功和失败的情况,或者使用 async/await 语法来简化异步代码。

  2. 简洁的语法fetch 的使用方式比 XHR 更加简洁直观。你只需要提供一个 URL 和一个可选的配置对象,而 XHR 需要多个步骤来设置请求方法、URL、请求头和响应处理。

  3. 更好的错误处理 : 使用 fetch,如果请求失败(例如网络问题或服务器错误),返回的 Promise 会被拒绝,这使得错误处理更加一致和清晰。

  4. 流式响应fetch 允许你以流式方式处理响应,这意味着你可以在数据到达时逐步处理它们,而不是等待整个请求完成。

  5. 跨域资源共享(CORS)fetch 自动处理 CORS 相关的预检请求(preflight requests),这使得跨域请求更加简单和直接。

  6. 更现代的 APIfetch 是一个较新的 API,它支持最新的网络特性,如 HTTP/2。而 XHR 是一个较老的技术,可能不支持一些现代的网络协议和特性。

  7. 更好的兼容性和维护性 : 由于 fetch 是一个现代标准,它在新版本的浏览器中得到了更好的支持。这意味着使用 fetch 的代码在未来可能更容易维护和升级。

  8. 红鸟(redbird)fetch API 提供了 redirect 模式,允许你控制请求的重定向行为。而 XHR 默认不支持跟踪重定向,除非你手动设置。

尽管 fetch API 有这些优势,但 XHR 仍然在一些旧的浏览器中更受欢迎,因此你可能需要为不支持 Promise 的环境提供 polyfill 或者继续使用 XHR。此外,fetch API 默认不会发送或接收 cookies,除非你明确设置 credentials 选项,这一点在使用某些需要身份验证的 API 时需要注意。

fetch封装:

为了创建一个通用的网络请求封装,我们可以定义一个对象或者一个类,其中包含各种HTTP请求方法,如 getpostputdelete 等。以下是一个使用对象方法封装 fetch API 的示例:

javascript 复制代码
// http.js

const API_BASE_URL = 'https://api.example.com'; // 基础URL,根据实际情况修改

const http = {
  get: (url, params) => {
    return fetch(`${API_BASE_URL}${url}`, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
      params: params, // 如果需要的话,可以传递查询参数
    })
    .then(response => {
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      return response.json();
    })
    .catch(error => {
      console.error('Error fetching data:', error);
      throw error;
    });
  },
  post: (url, body) => {
    return fetch(`${API_BASE_URL}${url}`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(body),
    })
    .then(response => {
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      return response.json();
    })
    .catch(error => {
      console.error('Error posting data:', error);
      throw error;
    });
  },
  // 可以继续添加put, delete等方法
  // ...
};

export default http;

在组件中使用封装的 http 对象:

javascript 复制代码
// SomeComponent.js
import http from './http';

// 使用GET请求获取数据
http.get('/data', { param: 'value'})
  .then(data => {
    console.log('Fetched data:', data);
  })
  .catch(error => {
    console.error('Error fetching data:', error);
  });

// 使用POST请求发送数据
const postData = { key: 'value' };
http.post('/data', postData)
  .then(response => {
    console.log('Posted data:', response);
  })
  .catch(error => {
    console.error('Error posting data:', error);
  });

在这个封装中,我们定义了一个 http 对象,它包含了 getpost 方法,以及其他可以添加的HTTP方法。每个方法都构建了一个完整的请求URL,设置了适当的HTTP方法和头部,并处理了响应。如果响应状态不是 2xx,就会抛出一个错误。这样的封装使得在项目中发起请求变得更加简单和一致。

请注意,这个封装示例假设所有的请求都返回JSON格式的数据。如果你的API返回其他格式的数据,你需要根据实际情况调整 .then 里面的处理逻辑。此外,你可能还需要添加请求拦截器、响应拦截器、错误统一处理、请求取消等功能,以满足项目的具体需求。

第五阶段:自己的项目,请求的封装

工作几个月后,陆续接触了不同的项目,包含umi开发的后台,next开发的c端官网和taro开发的小程序,每个项目都针对请求方法做了封装:

umi项目封装:

项目结构

vbscript 复制代码
一般封装的会放在utils/request.js中
util 
    ------------request 
        ------------config.js :配置常用的业务状态码 
        ------------httpErrorHandler.js:异常处理程序 
        ------------request.js :请求分装

config.js:

js 复制代码
export const SuccessCode = 0; 
export const LoginExpireTimeCode = 302; 
export const LoginUnLoginCode = '000014'; 
export const DefaultErrorCode = -1; 
export const DefaultBusinessErrorMsg = '业务逻辑错误'; 
export const DefaultHttpErrorCode = 5001; 
export const DefaultHttpErrorInfo = 'http请求出错,请稍后再试!'; 
export const DefaultNetErrorCode = 6001; 
export const DefaultNetErrorInfo = '网络异常,请检查网络连接!';

httpErrorHandler.js

js 复制代码
import {
  DefaultHttpErrorCode,
  DefaultHttpErrorInfo,
  DefaultNetErrorCode,
  DefaultNetErrorInfo,
} from './config';

const codeMessage = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队(异步任务)。',
  204: '删除数据成功。',
  400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限(令牌、用户名、密码错误)。',
  403: '用户得到授权,但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除,且不会再得到的。',
  422: '当创建一个对象时,发生一个验证错误。',
  500: '服务器发生错误,请检查服务器。',
  502: '网关错误。',
  503: '服务不可用,服务器暂时过载或维护。',
  504: '网关超时。',
};

/**
 * 异常处理程序
 */

const htttErrorHandler = (error) => {
  const { response } = error;
  if (response && response.status) {
    const errorText = codeMessage[response.status] || DefaultHttpErrorInfo;
    const { status } = response;

    return {
      code: status || DefaultHttpErrorCode,
      msg: errorText,
    };
  }

  return {
    code: DefaultNetErrorCode,
    msg: DefaultNetErrorInfo,
  };
};

export default htttErrorHandler;

request.js:将所有的错误情况都resolve,但是res为{error:{}}对象

js 复制代码
import { extend } from 'umi-request';
import { message } from 'antd';

/**
 * http error handler
 */
import httpErrorHandler from './httpErrorHandler';

import {
  SuccessCode,
  LoginExpireTimeCode,
  DefaultBusinessErrorMsg,
  DefaultErrorCode,
  DefaultNetErrorCode,
  DefaultNetErrorInfo,
  LoginUnLoginCode,
} from './config';

/**
 * 配置request请求时的默认参数
 */
const request = extend({
  // 处理http请求错误 未处理业务错误 业务错误baseRequest中处理
  errorHandler: httpErrorHandler,
  credentials: 'include', // 默认请求是否带上cookie
});

function baseRequest(url, options) {
  return new Promise((resolve) => {
    request(url, options)
      .then((response) => {
        const { code, msg, data } = response;
        // 业务正常
        if (code === SuccessCode || code === 200 || code === '0000') {
          resolve({
            data,
          });
        } else if (code === LoginExpireTimeCode || code === LoginUnLoginCode) {
          window.location.href = `${data.split('?')[0]}?_s=${encodeURIComponent(location.href)}`;
        } else {
          message.error(msg || DefaultBusinessErrorMsg);
          resolve({
            error: {
              errorCode: code || DefaultErrorCode,
              errorMsg: msg || DefaultBusinessErrorMsg,
            },
          });
        }
      })
      .catch(() => {
        resolve({
          error: {
            errorCode: DefaultNetErrorCode,
            errorMsg: DefaultNetErrorInfo,
          },
        });
      });
  });
}

baseRequest.get = (options) => {
  const { url } = options;
  return baseRequest(url, {
    ...options,
    // params:{...options},
    method: 'GET',
  });
};

baseRequest.post = (options) => {
  const { url } = options;
  return baseRequest(url, {
    ...options,
    method: 'POST',
  });
};

export default baseRequest;
相关推荐
昨天;明天。今天。1 小时前
案例-表白墙简单实现
前端·javascript·css
数云界1 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd1 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常1 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
ChinaDragonDreamer1 小时前
Vite:为什么选 Vite
前端
小御姐@stella1 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js
GISer_Jing1 小时前
【React】增量传输与渲染
前端·javascript·面试
GISer_Jing1 小时前
WebGL在低配置电脑的应用
javascript
eHackyd1 小时前
前端知识汇总(持续更新)
前端
万叶学编程5 小时前
Day02-JavaScript-Vue
前端·javascript·vue.js