This is the 23rd day of my participation in the August More Text Challenge.More challenges in August
1. Axios introduction and basic use
Axios is a Promise-based HTTP library that can be used in browsers and Node.js and supports the following features:
- Create XMLHttpRequests from the browser
- Create HTTP requests from Node.js
- Supporting Promise API
- Intercept requests and responses
- Transform request and response data
- Cancel the request
- Automatic conversion
JSON
data - The client supports XSRF defense
Reference:
axios-http.com/
www.npmjs.com/package/axi…
github.com/axios/axios
2, AXIOS source – AXIos class
The Axios class is the core class that encapsulates and provides the API used by the request.
/ / Axios class
function Axios() {
/ / initialization
}
Axios.prototype.request = function(config) {
// Axios unified request entry method
}
Copy the code
Axios also provides a list of HTTP method alias functions based on the request method:
// Provide aliases for supported request methods
// Encapsulate requests that do not need to submit body data
utils.forEach(['delete'.'get'.'head'.'options'].function forEachMethodNoData(method) {
/*eslint func-names:0*/
Axios.prototype[method] = function(url, config) {
return this.request(mergeConfig(config || {}, {
method: method,
url: url,
data: (config || {}).data
}));
};
});
// Handle requests that can submit body data
utils.forEach(['post'.'put'.'patch'].function forEachMethodWithData(method) {
/*eslint func-names:0*/
Axios.prototype[method] = function(url, data, config) {
return this.request(mergeConfig(config || {}, {
method: method,
url: url,
data: data
}));
};
});
Copy the code
6, Axios source code – factory functions
Axios provides a function createInstance to assist in creating an instance of the Axios class. Note, however, that instead of returning an Axios instance object, this function returns the instance object’s Request method, and mounts the instance object’s other alias methods to the Request method (functions are also objects, and attribute methods can be added). Hence the following usage:
axios({... }); axios.get('/', {...})
...
Copy the code
function createInstance(defaultConfig) {
var context = new Axios(defaultConfig);
var instance = bind(Axios.prototype.request, context);
// Copy axios.prototype to instance
utils.extend(instance, Axios.prototype, context);
// Copy context to instance
utils.extend(instance, context);
return instance;
}
Copy the code
When we reference the Axios library, it internally calls createInstance to initialize and returns Request:
varaxios = createInstance(defaults); .module.exports = axios;
// This is written to be compatible with the default export of the ESM module
module.exports.default = axios;
Copy the code
It also provides a few other methods for the exported AXIos:
Original class
// Mount the original Axios class
axios.Axios = Axios;
Copy the code
The factory function
// Create the instance's factory function
axios.create = function create(instanceConfig) {
return createInstance(mergeConfig(axios.defaults, instanceConfig));
};
Copy the code
So, we can create another AXIos request using the factory function:
// Use the default request
axios.get('/user');
// Use the new configuration to send the request
let newRequest = axios.create({baseURL: 'http://localhost:9999'});
newRequest.get('/user');
Copy the code
3, AXIos source code – configuration processing
There are three configuration points in Axios:
- Request method configuration
- The instance configuration
- Global configuration
Reference: axios-http.com/zh/docs/req…
Request method configuration
Is the configuration passed in request and alias methods such as GET and POST
axios({
url: '/user'
});
axios.get('/user', {
params: {
page:1.limit:2}})...Copy the code
Instantiate configuration
We can also pass in the base configuration at instantiation time (we can pass in some of the requested common configurations at instantiation time)
let newRequest = axios.create({
baseURL: 'http://localhost:9999'
});
Copy the code
Global (default) configuration
Axios also has a set of default configuration items, which are used if none are passed in at instantiation time or if the instantiation axios exports by default.
// The default configuration can be obtained via axios.defaults
axios.defaults.baseURL = 'http://localhost:8888';
axios.get('/user');
Copy the code
Configuring a Priority
Request Configuration > Instance Configuration > Default Configuration
4, AXIOS source code – interceptor application and implementation
There is a middleware-like mechanism in AXIos to handle tasks before the Request method requests them and after the response (before the user code executes).
// Add a request interceptor
axios.interceptors.request.use(function (config) {
// Do something before request is sent
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
return response;
}, function (error) {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
return Promise.reject(error);
});
Copy the code
Reference: axios-http.com/zh/docs/int…
Interceptor source code
Interceptors are essentially middleware arrays with two groups: requests and responses
function Axios(instanceConfig) {
this.defaults = instanceConfig;
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}
Copy the code
// Interceptor execution
Axios.prototype.request = function request(config) {...var requestInterceptorChain = [];
var synchronousRequestInterceptors = true;
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {
return;
}
synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
});
var responseInterceptorChain = [];
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
});
var promise;
if(! synchronousRequestInterceptors) {var chain = [dispatchRequest, undefined];
Array.prototype.unshift.apply(chain, requestInterceptorChain);
chain.concat(responseInterceptorChain);
promise = Promise.resolve(config);
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
}
var newConfig = config;
while (requestInterceptorChain.length) {
var onFulfilled = requestInterceptorChain.shift();
var onRejected = requestInterceptorChain.shift();
try {
newConfig = onFulfilled(newConfig);
} catch (error) {
onRejected(error);
break; }}try {
promise = dispatchRequest(newConfig);
} catch (error) {
return Promise.reject(error);
}
while (responseInterceptorChain.length) {
promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift());
}
return promise;
}
Copy the code
Interceptor application
// Add request interceptor
axios.interceptors.request.use(function (config) {
/ / send the token
try {
let token = localStorage.getItem('token');
config.headers.authorization = token;
} catch(e){}
return config;
}, function (error) {
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
console.log('Request Log', response);
return response;
}, function (error) {
console.log('Request Log', response);
alert('Wrong');
return Promise.reject(error);
});
Copy the code
5, AXIos source code – adapter
In the browser, we use the API provided by XMLHttpRequest to send the request. In node.js, we need to use the API provided by the HTTP module to send the request. The underlying API structure, including the formatting of the response data, is also inconsistent. Axios, in order to address this discrepancy and allow users to use the same API in different environments, uses adaptation mode.
graph RL
A[axios]
B[XMLHttpRequest Adapter] --> A
B1[XMLHttpRequest] --> B
C[Node.js Adapter] --> A
C1[Node.js] --> C