专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

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

ins518 2024-10-12 20:55:32 技术文章 12 ℃ 0 评论

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请求:

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请求

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):请求正在接收数据。在这个阶段,responseText 或 responseXML 属性可能会部分更新,但直到 readyState 变为 4,这些属性才是完整的。
  5. XMLHttpRequest.DONE (4):请求已完成。此时,服务器已经处理完毕请求,并且响应是最终的。如果 status 属性的值在 200 到 299 之间,说明请求成功;否则,请求失败。
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封装

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. 通过设置请求头,你可以传递认证令牌或其他自定义头信息。
  3. 响应处理
  4. 当请求成功时(HTTP 状态码在 200 到 299 之间),resolve 函数会被调用,返回响应数据。
  5. 如果请求失败(HTTP 状态码不在 200-299 之间),reject 函数会被调用,返回错误信息。
  6. 错误处理
  7. 如果请求过程中发生网络错误,onerror 事件处理器会被触发,reject 函数会被调用,返回错误信息。
  8. 跨域支持
  9. 请注意,跨域资源共享(CORS)需要服务器端设置适当的响应头。这个封装的函数不会改变服务器端的 CORS 策略,但它会正确处理浏览器的 CORS 策略。
  10. 数据格式
  11. 对于 POST 请求,如果提供了数据,函数会自动将数据序列化为 JSON 字符串,并设置请求头为 application/json。

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

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

  1. 引入 jQuery 库: 在你的 HTML 文件中,确保引入了 jQuery 库。你可以从 jQuery 官网获取最新版本的库,或者使用 CDN。
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

编写 AJAX 请求代码: 使用 $.ajax 方法来发送请求。这个方法接受一个配置对象,你可以在这个对象中设置请求的类型、URL、数据、请求头等。

$.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);
  }
});
  1. 处理响应: 在 success 回调函数中,你可以处理服务器返回的数据。如果请求失败,你可以在 error 回调函数中处理错误。
  2. 链式调用: 如果你需要在 AJAX 请求完成后执行其他操作,你可以使用 jQuery 的链式调用。
$.ajax({
  // ... AJAX 设置
}).done(function(response) {
  // 请求成功,可以在这里更新页面内容
  $('#data-container').html(response.html);
}).fail(function(jqXHR, textStatus, errorThrown) {
  // 请求失败,可以在这里显示错误信息
  $('#error-container').text('Error: ' + textStatus);
});

使用 $.get$.post 方法: 对于简单的 GET 和 POST 请求,jQuery 提供了更简洁的方法。

// 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

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 请求

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

发送 POST 请求

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

使用拦截器

// 添加请求拦截器
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);
});

取消请求

// 创建取消令牌
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 取消请求:

const controller = new AbortController();

axios.get('/foo/bar', {
   signal: controller.signal
}).then(function(response) {
   //...
});
// 取消请求
controller.abort()


这些示例展示了 Axios 的基本用法,包括发送 GET 和 POST 请求、使用拦截器以及取消请求。
Axios 的这些特性使其成为处理 HTTP 请求的强大工具,无论是在构建简单的前端应用还是复杂的后端服务时都非常有用。

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

封装的好处

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

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

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 和请求超时时间。我们还设置了请求拦截器和响应拦截器,用于序列化请求数据和处理响应数据。

然后,我们封装了一组请求方法 get、post、put、delete 和 patch,这些方法可以直接用于发起不同类型的 HTTP 请求。

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

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

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 请求

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 请求

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 关键字可以让异步代码看起来更像同步代码,从而简化错误处理和流程控制。

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. 更现代的 API: fetch 是一个较新的 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请求方法,如 get、post、put、delete 等。以下是一个使用对象方法封装 fetch API 的示例:

// 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 对象:

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

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

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

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

umi项目封装:

项目结构

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

config.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

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:{}}对象

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;

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表