Axios
function Axios(instanceConfig){
// Pass the configuration
this.defaults = instanceConfig
/ / the interceptor
this.interceptors = {
request: new InterceptorManager(),
respons: new InterceptorManager()
}
}
Axios.prototype.request = function request(config){
if(typeof config === 'string') {// Multiple parameters are passed
config = arguments[1] || {}
config.url = arguments[0]}else{
config = config || {}
}
config = mergeConfig(this.default,config)
// Declare the request method by default
if(config.method){
config.method = config.method.toLowerCase()
}else if(this.defaults.method){
config.method = this.defaults.method.toLowerCase()
}else{
config.method = 'get'
}
var transitional = config.transitional
if(transitional ! = =undefined){
validator.assertOptions(transitional,{
slientJSONParsing: validators.transitional(validators.boolean,'1.0.0'),
forcedJSONParsing: validators.transitional(validators.boolean,'1.0.0'),
clarifyTimeoutError:validators.transitional(validators.boolean,'1.0.0')},false)}// Store request interceptors
var requestInterceptorChain = []
// The default synchronization request interception is interception before request
var synchronousRequestInterceptors = true
this.interceptors.request.forEach(function(interceptor){
// The runtime determines whether the request continues
if(typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {return
}
synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous
// Storage interception succeeded/failed
requestInterceptorChain.unshift(interceptor.fulfilled,interceptor.rejected)
})
// Store interception after request
var responseInterceptorChain = []
this.interceptors.response.forEach(function(interceptor){
responseInterceptorChain.push(interceptor.fulfilled,interceptor.rejected)
})
var promise
// Request interception is out of sync
if(! synchronousRequestInterceptors){// Request queue request interception success/failure/request/response interception/response interception failure
var chain = [dispatchRequest,undefined]
Array.prototype.unshift.apply(chain,requestInterceptorChain)
chain.conat(responseInterceptorChain)
// return request configuration
primise = Promise.resolve(config)
// The queue on which the request is executed
while(chain.length){
promise = promise.then(chain.shift(),chain.shift())
}
return promise
}
// Synchronize request + intercept
var newConfig = config
while(requestInterceptorChain.length){
var onFulfilled = requestInterceptorChain.shift()
var onRejected = requestInterceptorChain.shift()
// Parse the request interception configuration
try{
newConfig = onFulfilled(config)
}catch(error){
onRejected(err)
break}}// Initiate a request
try{
promise = dispatchRequest(newConfig)
}catch(error){
return Promise.reject(error)
}
// Respond to interception if the request succeeds
while(responseInterceptorChain.length){
promise = promise.then(responseInterceptorChain.shift(),responseInterceptorChian.shift())
}
return promise
}
/ / get a uri
Axios.prototype.getUri = function getUri(config){
config = mergeConfig(this.defaults,config)
return buildURL(config.url,config.params,config.paramsSerializer).replace(/ ^ \? /.' ')}// Define the delete/get/head/options methods
utils.forEach(['delete'.'get'.'head'.'options'].function(method){
Axios.prototype[method] = function(url,config){
return this.request(mergeConfig(config||{},{
method,
url,
data:(config || {}).data
}))
}
})
// Define the post/put/patch methods
utils.forEach(['post'.'put'.'patch'].function(method){
Axios.prototype[method] = function(url,data,config){
return this.request(mergeConfig(config || {},{
method,url,data
}))
}
})
Copy the code
InterceptorManager
// Interceptor class
function InterceptorManager(){
// Store interceptor operations
this.handlers = []
}
// Store interceptor operations
InterceptorManager.prototype.use = function use(fulfilled,rejected,options){
this.handlers.push({
fulfilled:fulfilled,
rejcted:rejected,
synchronous: options ? options.synchronous : false.runWhen: options ? options.runWhen : null
})
return this.handlers.length - 1
}
// Clear the interceptor
InterceptorManager.prototype.eject = function eject(id){
if(this.handlers[id]){
this.handlers[id] = null
}
}
InterceptorManager.prototype.forEach = function forEach(fn){
utils.forEach(this.handlers,function forEachHandler(h){
if(h ! = =null){
fn(h)
}
})
}
Copy the code
mergeConfig
function mergeConfig(config1,config2){
config2 = config2 || {}
var config = {}
var valueFromConfig2Keys = ['url'.'method'.'data']
var mergeDeepPropertiesKeys = ['headers'.'auth'.'proxy'.'params']
var defaultToConfig2Keys = ['baseURL'.'transformRequest'.'transformResponse'.'paramsSerializer'.'timeout'.'timeoutMessage'.'withCredentials'.'adapter'.'responseType'.'xsrfCookieName'.'xsrfHeaderName'.'onUploadProgress'.'onDownloadProgress'.'decompress'.'maxContentLength'.'maxBodyLength'.'maxRedirects'.'transport'.'httpAgent'.'httpsAgent'.'cancelToken'.'socketPath'.'responseEncoding']
var directMergeKeys = ['validateStatus']
/ / target/source
function getMergedValue(target,source){
if(utils.isPlainObject(target) && utils.isPlainObject(source)){
return utils.merge(target,source)
}else if(utils.isPlainObject(source)){
return utils.merge({},source)
}else if(utils.isArray(source)){
return source.slice()
}
return source
}
// extend config2 to config1
function mergeDeepProperties(prop){
if(! utils.isUndefined(config2[prop])){ config[prop] = getMergedValue(config1[prop],config2[prop]) }else if(! utils.isUndefined(config1[prop])){ config[prop] = getMergedValue(undefined,config1[prop])
}
}
// Use request to configure the URL /method/data
utils.forEach(valueFromConfig2Keys,function(prop){
if(! utils.isUndefined(conifg2[prop])){ config[prop] = getMergedValue(undefined,config2[prop])
}
})
/ / headers/merger auth/proxy/params
utils.forEach(mergeDeepPropertiesKeys,mergeDeepProperties)
// Config2 configuration request is preferred
utils.forEach(defaultToConfig2Keys.function(prop){
if(! utils.isUndefined(config2[prop])){ conifg[prop] = getMergedValue(undefined,config2[prop])
}else if(! utils.isUndefined(config1[prop])){ config[prop] = getMergedValue(undefined,config1[prop])
}
})
// config1 > config2 [validateStatus]
utils.forEach(directMergeKeys,function(prop){
if(prop in config2){
config[prop] = getMergedValue(config1[prop],config2[prop])
}else if(prop in config1){
config[prop] = getMergedValue(undefined,config1[prop])
}
})
var axiosKeys = valueFromConfig2Keys.concat(mergeDeepPropertiesKeys).concat(defaultToConfig2Keys).concat(directMergeKeys)
const otherKeys = Object.keys(config1).concat(Object.keys(config2)).filter(function filterAxiosKeys(key) {
return axiosKeys.indexOf(key) === -1
})
// Merge other attributes
utils.forEach(otherKeys,mergeDeepProperties)
return config
}
Copy the code
buildURL
function buildURL(url,params,paramsSerializer){
// Argument does not exist to return url directly
if(! params){return url
}
var serializedParams
// Serialize parameters
if(paramsSerializer){
serializedParams = paramsSerializer(params)
} else if(utils.isURLSearchParams(params)){
serializedParams = params.toString()
}else{
var parts = []
// Iterate over the parameters
utils.forEach(params,function(val,key){
if(val === null|| typeof val === 'undefined') {return
}
// Check whether the current parameter key is an array
if(utils.isArray(val)){
key = key + '[]'
}else{
val = [val]
}
// Get arguments in different formats
utils.forEach(val,function(v){
if(utils.isDate(v)){
v = v.toISOString()
}else if(utils.isObject(v)){
v = JSON.stringify(v)
}
parts.push(encode(key)+'='+ encode(v))
})
})
// Merge parameters
serializedParams = parts.join("&")}if(serializedParams){
var hashmarkIndex = url.indexOf(The '#')
// Determine if the hash exists to take a non-hashURL
if(hashmarkIndex ! = = -1){
url = url.slice(0,hashmarkIndex)
}
/ / judgment? Whether a combination parameter exists
url = (url.indexOf('? ') = = = -1 ? '? ' : '&') + serializedParams
}
return url
}
Copy the code
encode
function encode(val){
// encode :/&/,/+/[/
return encodeURIComponent(val).replace(/%3A/gi.':').relace(/%24/g.'&').replace(/%2C/gi.', ').replace(/%20/g.'+').relace(/%5B/gi.'[').relace(/%5D/gi.'] ')}Copy the code
validator
var pkg = require('.. /.. /.. /package.json')
var validators = {}
// Determine the data type
['object'.'boolean'.'number'.'function'.'string'.'symbol'].forEach(function(type,i){
validators[type] = function(thing){
return typeof thing === type || 'a' + (i < 1 ? 'n' : ' ') + type
}
})
var deprecateWarnings = {}
// Get the current version
var currentVerArr = pkg.version.split('. ')
// Compare the version to an earlier version
function isOlderVersion(version,thanVersion){
var pkgVersionArr = thanVersion ? thanVersion.split('. ') : currentVerArr
var destVer = version.split('. ')
for(var i = 0; i < 3; i ++){
if(pkgVersionArr[i] > destVer[i]){
return true
}else if(pkgVersionArr[i] < destVer[i]){
reurn false}}return false
}
Copy the code
assetOptions
function assetOptions(option,schema,allowUnKonwn){
// Transitional must be an object
if(typeofoptions ! = ='object') {throw new TypeError('options must be an object')}var keys = Object.keys(options)
var i = keys.length
/ / traverse transitional
while(i -- > 0) {var opt = keys[i]
var validator = schema[opt]
if(validator){
/ / determine transitional
const value = options[opt]
// Skip without setting/Verify after setting
var result = value === undefined || validator(value,opt,options)
if(result ! = =true) {throw new Error('option'+opt+'must be'+result)
}
continue
}
// Unknown configuration
if(allowUnKnown ! = =true) {throw new Error('unKnown option:'+opt)
}
}
}
Copy the code
transitional
validators.transitional = function (validator,version,message){
// Check whether the current version is expired
var isDeprecated = version && isOlderVersion(version)
function formatMessage(opt,desc){
return '[Axios v'+pkg.version+'] Transitional Option\''+opt+'\' '+desc+(message ? '. ' + message : ' ')}return function(value,opt,opts){
if(validator === false) {// JSONParsing false
throw new Error(formatMessage(opt,'has been removed in'+ version))
}
if(isDeprecated && ! deprecatedWarnings[opt]){ deprecatedWarnings[opt] =true
console.warn(formatMessage(opt,'has been deprecated since v '+ version + 'and will be removed in the near future'))}// Verify that the transitional Boolean is true
return validator ? validator(value,opt,opts) : true}}Copy the code