根据官方文档,我们知道axios支持nodejs、浏览器环境,但不支持uniapp、小程序,所以要想在uniapp中使用axios就要自定义实现。axios文档对自定义实现,作了说明。
// `adapter` allows custom handling of requests which makes testing easier.// Return a promise and supply a valid response (see lib/adapters/README.md).adapter: function (config) {/* ... */},
翻译过来就是,要想自定义实现,就要覆盖adapter方法,默认实现如下
var settle = require('./../core/settle');module.exports = function myAdapter(config) {// At this point:// - config has been merged with defaults// - request transformers have already run// - request interceptors have already run// Make the request using config provided// Upon response settle the Promisereturn new Promise(function(resolve, reject) {var response = {data: responseData,status: request.status,statusText: request.statusText,headers: responseHeaders,config: config,request: request};settle(resolve, reject, response);// From here:// - response transformers will run// - response interceptors will run});
}
settle.js中的代码
'use strict';import AxiosError from './AxiosError.js';/*** Resolve or reject a Promise based on response status.** @param {Function} resolve A function that resolves the promise.* @param {Function} reject A function that rejects the promise.* @param {object} response The response.** @returns {object} The response.*/
export default function settle(resolve, reject, response) {const validateStatus = response.config.validateStatus;if (!response.status || !validateStatus || validateStatus(response.status)) {resolve(response);} else {reject(new AxiosError('Request failed with status code ' + response.status,[AxiosError.ERR_BAD_REQUEST, AxiosError.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4],response.config,response.request,response));}
}
结合uniapp的api,可对axios如此封装
let count = 0
axios.defaults.adapter = function(config) { //自己定义个适配器,用来适配uniapp的语法count++if (count == 1) {uni.showLoading({title: "加载中",mask:true})}return new Promise((resolve, reject) => {var settle = require('axios/lib/core/settle');var buildURL = require('axios/lib/helpers/buildURL');uni.request({method: config.method.toUpperCase(),url: config.baseURL + config.url,header: config.headers,data: config.data,dataType: config.dataType,responseType: config.responseType,sslVerify: config.sslVerify,complete: function complete(response) {count--if (count == 0) {uni.hideLoading()}if (response.data.code != 200) {uni.showToast({title: response.data.msg,duration: 5000,icon: 'none'})reject(response.data.msg)return}response = {data: response.data,status: response.statusCode,errMsg: response.errMsg,header: response.header,config: config};settle(resolve, reject, response);}})})
}
我们不禁要问,直接用uni.request
封装请求不更简单吗?比如,
function request(data){return new Promise((resolve,reject)=>{uni.request({data,complete:function(response){resolve(response);}})})
}
这样做是可以,但没有了拦截器、baseUrl、参数转换等功能;基于axios封装,可以使用axios的api,比如拦截器。
// 添加请求拦截器
axios.interceptors.request.use(function (config) {// 在发送请求之前做些什么return config;}, function (error) {// 对请求错误做些什么return Promise.reject(error);});// 添加响应拦截器
axios.interceptors.response.use(function (response) {// 2xx 范围内的状态码都会触发该函数。// 对响应数据做点什么return response;}, function (error) {// 超出 2xx 范围的状态码都会触发该函数。// 对响应错误做点什么return Promise.reject(error);});
总结
- uniapp中使用axios,是为了按照axios的风格来发送请求,并且axios提供了请求拦截器、响应拦截器、baseUrl、请求参数自动转换等功能;否则就要自己实现;
- 通过axios开放的adapter方法来适配uniapp环境,uniapp中发送去请求的api是uni.request。