前端数据请求(axios,jQuery,原生)

2020/11/6 JavaScript

# jQuery的ajax

$.ajax({
  url: '127.0.0.1:3000', // 请求的url地址
  type: 'GET', // 请求方式
  contentType: 'application/x-www-form-urlencoded;charset=UTF-8', // 请求参数类型
  async: true, // 请求是否异步,默认为异步,这也是ajax重要特性
  data: { id: 'value' }, // 参数值
  dataType: 'json', // 返回格式为json
  beforeSend() { }, // 请求前
  success(req) { }, // 请求成功时
  complete() { }, // 请求完成
  error() { }, // 请求出错
});
1
2
3
4
5
6
7
8
9
10
11
12

# 原生请求

/**
 * 格式化请求参数
 * @param { Object } data
 */
function formatData(data) {
  const tempArr = [];
  if (data.constructor === Object) {
    Object.keys(data).forEach((key) => {
      tempArr.push(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`);
    });
  }
  return tempArr.join('&');
}

/**
 * @param { Object } options 格式同jquery ajax
 */
function ajax(options) {
  const type = (options.type || 'GET').toUpperCase();
  const contentType = options.contentType || 'application/x-www-form-urlencoded;charset=UTF-8';
  const async = options.async === undefined ? true : Boolean(options.async); // 是否异步请求
  const params = formatData(options.data);

  let xhr = null;
  if (window.XMLHttpRequest) { // code for IE7, Firefox, Opera, etc.
    xhr = new XMLHttpRequest();
  } else if (window.ActiveXObject) { // code for IE6, IE5
    xhr = new ActiveXObject('Microsoft.XMLHTTP');
  }
  if (xhr !== null) {
    // 设置超时
    if (options.timeout && options.timeout > 0) {
      xhr.timeout = options.timeout;
    }
    return new Promise((resolve, reject) => {
      if (type === 'GET') {
        xhr.open(type, `${options.url}?${params}`, async);
        xhr.send();
      } else if (type === 'POST') {
        xhr.open(type, options.url, async);
        // 设置表单提交时的内容类型 Content-type数据请求的格式
        xhr.setRequestHeader('Content-type', contentType);
        xhr.send(params);
      }
      // readyState 共五种状态
      // 0  Uninitialized 初始化状态。XMLHttpRequest 对象已创建或已被 abort() 方法重置。
      // 1  Open  open() 方法已调用,但是 send() 方法未调用。请求还没有被发送。
      // 2  Sent  Send() 方法已调用,HTTP 请求已发送到 Web 服务器。未接收到响应。
      // 3  Receiving 所有响应头部都已经接收到。响应体开始接收但未完成。
      // 4  Loaded  HTTP 响应已经完全接收。
      xhr.onreadystatechange = () => {
        if (xhr.readyState === 4) {
          if (xhr.status >= 200 && (xhr.status < 300 || xhr.status === 304)) {
            resolve(xhr.responseText);
          } else {
            reject(new Error(xhr.responseText));
          }
        }
      };
      xhr.ontimeout = () => reject(new Error('请求超时'));
      xhr.onerror = (err) => reject(err);
    });
  }
  throw new Error('Your browser does not support XMLHTTP.');
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

# Axios

Axios 中文说明 (opens new window)

特性

  • 从浏览器中创建XMLHttpRequests
  • node.js创建http请求。
  • 支持PromiseAPI。
  • 拦截请求和响应。
  • 转换请求数据和响应数据。
  • 取消请求。
  • 自动转换JSON数据。
  • 客户端支持防御XSRF

基本使用

import axios from 'axios';

axios({
  url: 'xxx', // 设置请求的地址
  method: 'GET', // 设置请求方法
  params: { // get请求使用params进行参数凭借,如果是post请求用data
    type: '',
    page: 1,
  },
}).then((res) => {
  // res为后端返回的数据
  console.log(res);
}).catch((err) => {
  console.log(err);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

请求的简单封装

import axios from 'axios';
import qs from 'qs';
import { isIE } from 'element-ui/lib/utils/util';

// 创建请求成功的转换
function requestTransform(request) {
  // 添加一些公用的请求头
  request.headers.Authorization = 'token';

  if (request.method === 'post') {
    if (request.contentType === 'json') {
      request.headers['Content-Type'] = 'application/json;charset=utf-8';
      request.data = JSON.stringify(request.data);
    } else if (request.contentType === 'formData' || !request.contentType) {
      request.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
      request.data = qs.stringify(request.data);
    }
  }

  if (request.method === 'get' && isIE()) {
    if (!request.params) {
      request.params = {};
    }
    // 防止IE缓存
    request.params.temp = Date.now();
  }
  return request;
}

// 创建请求失败
function requestFail(error) {
  return Promise.reject(error);
}

// 响应拦截器成功转换
function responseTransform(response) {
// 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据
  // 否则的话抛出错误
  if (response.status === 200) {
    if (response.data.code === 401) {
      // 未授权调取授权接口
      return Promise.reject(response);
    }
    if (response.data.code === 500) {
      // 请求失败
      return Promise.reject(response);
    }
    return Promise.resolve(response);
  }
  return Promise.reject(response);
}

// 响应拦截器失败处理
function responseFail(error) {
  // 我们可以在这里对异常状态作统一处理
  if (error.message.indexOf('timeout') !== -1) {
    console.error('response', 'timeout');
  }
  // 处理请求失败的情况
  return Promise.reject(error.response);
}

function create(config) {
  const conf = {
    baseURL: '',
    timeout: 20000,
    ...config,
  };
  const instance = axios.create(conf);

  // 请求拦截器
  instance.interceptors.request.use(requestTransform, requestFail);
  // 响应拦截器
  instance.interceptors.response.use(responseTransform, responseFail);

  return instance;
}

// 调用示例
const request = create({
  baseURL: 'http://127.0.0.1:8080/api/',
});
request.get('/getUser', { params: { name: 'xxx' } }).then((resp) => {
  console.log(resp);
}).catch((err) => {
  console.log(err);
});
request.post('/addUser', { name: 'xxx' });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
最近更新: 2024年08月14日 16:42:18