axios攻略

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

Features

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

axios有两种用法。

// 为给定 ID 的 user 创建请求
axios.get('/user?ID=12345')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });
  
// 也可以通过 params 对象传递参数
axios.get(‘/user’, {
	params: {ID: 12345}
}).then(response => {
	console.log(response);
}).catch(error => {
	console.log(error);
});
// 发送 POST 请求
axios({
  method: 'post',
  url: '/user/12345',
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
}).then(response => {
});

axios的响应结构

{
  // `data` 由服务器提供的响应
  data: {},

  // `status` 来自服务器响应的 HTTP 状态码
  status: 200,

  // `statusText` 来自服务器响应的 HTTP 状态信息
  statusText: 'OK',

  // `headers` 服务器响应的头
  headers: {},

  // `config` 是为请求提供的配置信息
  config: {}
}

在实际请求后台接口时,会要求前端传入规定格式的数据,比如jsonaxios会在请求之前判断传值的类型,并以相应的content-type发送请求到后台服务器。在这个过程中踩了不少坑,特此,做一个总结。

  1. 坑1
    在使用axios发送post请求时,默认的请求头Content-Type的属性值为application/json,这个时候浏览器会分两次发送请求,首先使用OPTION方法发送请来询问服务对请求是否支持,若不支持,则报错,终止请求的发送。
  2. 坑2
  • 如果用urlSearchParams对象传递参数,那么content-type的值为application/x-www-form-urlencoded;charset=utf-8
  • 如果用json对象传递参数,那么content-type的值为application/json;charset=utf-8
    axios的源码
axios.create = function create(instanceConfig) {
  return createInstance(utils.merge(defaults, instanceConfig));
};

create方法就是把我们传入的参数和默认参数合并,然后创建一个axios实例,我们再看看defaults这个配置对象

var utils = require('./utils');
var normalizeHeaderName = require('./helpers/normalizeHeaderName');
/* 这个表明默认的Content-Type就是我们想要的 */
var DEFAULT_CONTENT_TYPE = {
  'Content-Type': 'application/x-www-form-urlencoded'
};
/* 看方法名就知道,这个是设置ContentType用的(Content-Type没有设置的时候) */
function setContentTypeIfUnset(headers, value) {
  if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {
    headers['Content-Type'] = value;
  }
}
/* 这个是用来区别对待浏览器和nodejs请求发起工具的区别的 */
function getDefaultAdapter() {
  var adapter;
  if (typeof XMLHttpRequest !== 'undefined') {
    // For browsers use XHR adapter
    adapter = require('./adapters/xhr');
  } else if (typeof process !== 'undefined') {
    // For node use HTTP adapter
    adapter = require('./adapters/http');
  }
  return adapter;
}
/* 这里终于看到了万众期待的默认配置 */
var defaults = {
  adapter: getDefaultAdapter(),
  /* 这个transformRequest配置就厉害了
   * 官方描述`transformRequest` allows changes to the request data before it is sent to the server 
   * 这个函数是接受我们传递的参数,并且在发送到服务器前,可以对其进行更改
   * */
  transformRequest: [function transformRequest(data, headers) {
    normalizeHeaderName(headers, 'Content-Type');
    if (utils.isFormData(data) ||
      utils.isArrayBuffer(data) ||
      utils.isStream(data) ||
      utils.isFile(data) ||
      utils.isBlob(data)
    ) {
      return data;
    }
    if (utils.isArrayBufferView(data)) {
      return data.buffer;
    }
    /* 关键点1、如果用URLSearchParams对象传递参数,就可以用我们想要的Content-Type传递 */
    if (utils.isURLSearchParams(data)) {
      setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');
      return data.toString();
    }
    /* 关键点2、这里我们看到,如果参数Object的话,就是通过json传递 */
    if (utils.isObject(data)) {
      setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
      return JSON.stringify(data);
    }
    return data;
  }],
  transformResponse: [function transformResponse(data) {
    /*eslint no-param-reassign:0*/
    if (typeof data === 'string') {
      try {
        data = JSON.parse(data);
      } catch (e) { /* Ignore */ }
    }
    return data;
  }],
  timeout: 0,
  xsrfCookieName: 'XSRF-TOKEN',
  xsrfHeaderName: 'X-XSRF-TOKEN',
  maxContentLength: -1,
  validateStatus: function validateStatus(status) {
    return status >= 200 && status < 300;
  }
};
defaults.headers = {
  common: {
    'Accept': 'application/json, text/plain, */*'
  }
};
utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {
  defaults.headers[method] = {};
});
utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);
});
module.exports = defaults;

综上述,欲传递表单数据,则通过urlSearchParams对象。示例:

import axios from 'axios';

let param = new URLSearchParams();
param.append("username", "admin");
param.append("password", "admin");

axios({
	method:'post',
	url:'/login',
	data:param
}).then(response => { });

参考地址

  1. 坑3
    当没有参数传递时,设置的content-type的无用。
    axios源码如下:
 // Add headers to the request
    if ('setRequestHeader' in request) {
      utils.forEach(requestHeaders, function setRequestHeader(val, key) {
        if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {
          // Remove Content-Type if data is undefined
          delete requestHeaders[key];
        } else {
          // Otherwise add header to the request
          request.setRequestHeader(key, val);
        }
      });
    }

参考地址

  1. 坑4
    参考链接

  2. 坑5

this.$axios({
	method:'get',
    url:'/api/portal/login?loginName='+this.loginName+'&password='+this.password
}).then((response)=>{
    console.log(response);
})

这种方式请求头中content-type的值为application/json;charset=UTF-8

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值