Vue uses Axios for HTTP communication, similar to the role of Jquery/ajax, similar to the role of angular HTTP, Axios powerful, easy to use, is an excellent HTTP software, the purpose of this article is to share the key points of Axios source code analysis, The details of the source code are not intended to be thoroughly analyzed from beginning to end.
Axios does a complex and esoteric package, unlike a common object/instance approach.
Debug See Axios.get () code is:
Bind.js:
Module.exports = function bind (FN, Thisarg) {
return function wrap () {//axios is this method
var args = new Array (arguments.length);
for (var i = 0; i < args.length; i++) {
Args[i] = arguments[i];
}
Return fn.apply (Thisarg, args);
};
Look at the Axios Portal file axios.js code:
Function CreateInstance (defaultconfig) {
var context = new Axios (defaultconfig);// This is the Axios instance
var instance = bind (Axios.prototype.request, context);//bind returns the Wrap method instead of the Axios instance
//Copy Axios.prototype to Instance
Utils.extend (instance, axios.prototype, context);//Copy the Axios static object's property method to instance, Because you want to change the this pointer in the property method, you cannot simply copy the property method,
But to write the Warp method, which returns Fn.apply (Context,args), then when the property method is called, The Wrap method is executed, or the
Fn.apply then returns, which is to add a wrapper to the method fn to adjust the pointer, otherwise the property method is Fn is simple.
//Copy context to instance
Utils.extend (instance, context);//Copy the attribute method of the Axios instance to instance
return instance;
}
var Axios = CreateInstance (defaults);//defaults object is the default configuration data, obtained with Var defaults=require ('./defaults ')
Module.exports = Axios;
In bind see FN is:
Axios.prototype.request
Axios.prototype[method]
FN is the property method of the Axios static object: Request,get, the Get method code is as follows:
Utils.foreach ([' Delete ', ' get ', ' head '], function Foreachmethodnodata (method) {
Axios.prototype[method] = function (url, config) {
Return this.request (utils.merge (config | | {}, {//this has been adjusted to Axios instance when calling this method
Method:method,
Url:url
}));
};
Is the request method that executes the Axios instance.
In the extend code with debug see Axios.prototype has the following attribute method:
Request
Delete
Get
Head
Post
Put
Patch
Defaults
Interceptors
These property methods are copied to Axios,axios with these property methods, so you can write Axios.get call their methods, but debug looks at Axios as a wrap method,
is a constructor, is also an object, is a special object, not the new Axios () instantiation, see Axios see Properties, but see Axios.get is there,
There is no axios.abc to see.
So Axios is a very special constructor/object, its property method is also special constructs, is the wrap () function, the code is fn.apply (), so
When calling Axios.get, it is really the Get property method that calls the Axios object, which is called the Axios.prototype.get method, Axios is the prototype, and Axios is a
Instance,instance inherits the prototype and adjusts this to the prototype instance new Axios () when invoking the prototype method.
This programming method is very advanced, supposedly, is generally new Axios (), and then call the instance of the property method, very simple, but it is not so designed, it is designed
A special object Axios, and then Axios as a prototype copy to Axios, then Axios is a axios of the prototype, and then adjust the method of this to
The new Axios instance so that when you call the Axios property method, it is equivalent to calling the property method of the new Axios instance.
Defining a standard prototype Axios, and then creating a instance (Axios), is unthinkable, so designed to be hierarchical, to prototype and instance
Separate.
Axios is actually Axios, just axios itself and attribute methods do a package.
- Axios Key Source Code Analysis
You can see all of the property names of the Axios by using the Loop method:
for (var key in Axios) {
Console.log (key);
};
Request
Delete
Get
Head
Post
Put
Patch
Defaults
Interceptors
Axios
Create
Cancel
Canceltoken
Iscancel
All
Spread
Default
So Axios.defaults is the defaults property that accesses/modifies Axios and is also copied from Axios.prototype, and the Copy property/Access property does not have this problem.
Calling Axios.get is actually calling the Axios.prototype.get prototype method, which represents the new Axios instance:
Utils.foreach ([' Delete ', ' get ', ' head '], function Foreachmethodnodata (method) {
Axios.prototype[method] = function (url, config) {
Return this.request (utils.merge (config | | {}, {
Method:method,
Url:url
}));
The Get method is called the request method, which means: ' Get ', so the Axios.get code is actually starting with the request code:
Axios.prototype.request = function Request (config) {
Config = utils.merge (defaults, This.defaults, {method: ' get '}, config);
Axios.defaults will be merged into Config,config, which is just the data passed in, which adds properties such as Data,baseurl.
Config.url = Combineurls (Config.baseurl, Config.url); Stitching URLs, call get when you enter an absolute URL path and no more stitching
Promise = Promise.then (http intercept function/dispatchrequest); This HTTP procedure has nested promise
return promise; For Axios.get () and then (callback)
function Dispatchrequest (config) {
Config.headers = Utils.merge (
Config.headers.common | | {},
Config.headers[config.method] | | {},
Config.headers | | {}
);
You can see that the Axios.headers.common or axios.headers["Get" is written as the header property configuration will be merged into headers, so like axios.defaults.headers.common[" Access_token "] =" 123456 "The result is the same.
return Adapter (config). Then (function onadapterresolution (response) {
return response;
}, function onadapterrejection (reason) {
return promise.reject (reason);
function Xhradapter (config) {
return new Promise (function dispatchxhrrequest (resolve, Reject) {
var requestData = Config.data;
var requestheaders = config.headers;
Utils.foreach (requestheaders, Function setRequestHeader (val, key) {
Request.setrequestheader (Key, Val);
To set the HTTP Request header property in the adapter bottom setRequestHeader native method, look at the HTTP header as:
Request Headers:
Accept:application/json, Text/plain, */*//This property is the default property of the Axios setting
Accept-encoding:gzip, deflate, BR
accept-language:zh-cn,zh;q=0.8
access_token:123456
Authorization:token 4B26496037665E0C4D308EC682B6E7FB
Test:hello
One of the properties is the global property set in Http.js (each HTTP request is valid):
axios.defaults.headers["Access_token"] = "123456";
For a specific HTTP request, you can also pass a JSON object {} to set the Http/header property, similar to the jquery Ajax notation:
Axios.get (url,{
headers:{
Test: "Hello"
},
params:{
ID: "123456"//Because it is a GET request, this parameter is automatically appended to the URL in the form of a query string, as it is written directly at the URL id=123456.
}
)
Some properties are the default property used by browsers for HTTP communication.
Therefore, the HTTP parameter configuration, one can write the global configuration in Http.js, and the other is to call the Get method directly write a {property name: Property value} can be passed in,
Axios the agreed property name can refer to the API, you can also directly look at the original code, write parameters like jquery Ajax, are in JSON object form, such as:
{
Headers: {' x-requested-with ': ' XMLHttpRequest '},
Params: {//As query string parameter
id:12345
},
Data: {//Post data
FirstName: ' Fred '
},
timeout:1000,//http request timeout can be configured each time it is requested, the default is 5s
}
The calling notation is similar to jquery Ajax: Axios.get (url,{}), where the config data in the original code is the incoming {}.
The original code is:
Path:buildurl (Parsed.path, Config.params, Config.paramsserializer). Replace (/^\?/, '),
This is a parameter that constructs a URL when it is constructed using the params property of the Config object. a=b.
Axios function is very strong, support upload/download progress processing, canceltoken mechanism, also support proxy, generally only the project-level software support proxy,
such as the Ionic project environment.
The bottom adapter have http.js and xhr.js two, xhr.js no proxy processing code, decide with which adapter code:
Dispatchrequest:
var adapter = Config.adapter | | Defaults.adapter;
If there is a custom adapter, the custom adapter is executed, otherwise the default adapter is executed, and the default adapter is the following decision:
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;
If the browser is executed XHR, does not support proxy, if run in Nodejs, with HTTP adapter, support proxy, so proxy is the function of Nodejs.
On the basis of Axios, it can be further encapsulated, such as FECTH is called GET, but made a layer of encapsulation:
function fetch (URL, params = {}) {
return new Promise ((resolve, reject) = {
Axios.get (URL, {
Params:params
})
. Then (response = {
Resolve (response); Because the callback is passed resolve when it is a new instance, it is a resove new instance
})
. catch (Err = {
Reject (ERR)
})
Bulk HTTP notation:
Axios.all ([Getcarousel (), Getthemes (), Gethotline (), Getarea ()])
. Then (Axios.spread (function (Getcarouseldata, Getthemesdata, Gethotlinedata, Getareadata) {
The same is true for Axios.get (URL) or fetch (URL), but adding a layer of encapsulation is logically more intuitive.
- Axios.all () Source code Analysis for bulk HTTP execution
Axios.spread Method Code:
function spread (callback) {
return function wrap (arr) {
return callback.apply (null, arr);
};
It returns a wrap wrapper function, so actually it is then (function wrap (arr) {return callback.apply (Null,arr);}), Promise
Will resolve before the promise instance passes the data execution then inside the function, passes the data is the array, the function parameter writes,,, is possible, the function code uses
Arguments[] Take parameters can also be removed spread direct write then (Funciton () {is also possible, with Arguments[0] can get to the array, Axios transform
The parameter is added with a layer [0].
The key is to see how all promise resolve, involving each HTTP promise state change, quite complicated.
Axios.all Code:
Axios.all = function All (promises) {
Return Promise.all (promises);
};
Es6-promise:
function all (entries) {
return new Enumerator (this, entries). Promise;
}
Function Enumerator (Constructor, input) {
This.promise = new Constructor (NOOP); All returns this promise instance
This._result = new Array (this.length);
This._enumerate ();
Fulfill (this.promise, this._result); Here resolve returns the promise instance and passes an array
Enumerator.prototype._enumerate = function () {
This._eachentry (_input[i], i);
Enumerator.prototype._eachentry = function (entry, i) {
This._settledat (Entry._state, I, Entry._result);
This._willsettleat (resolve$$ (entry), i);
this._remaining--;
This._result[i] = entry;
Enumerator.prototype._settledat = function (state, I, value) {
Check to process a promise, update all promise array as well as count if complete
this._remaining--;
This._result[i] = value;
if (this._remaining = = = 0) {
If all HTTP promise are complete then resolve Axios.all returns promise
Fulfill (promise, This._result);
Enumerator.prototype._willsettleat = function (Promise, I) {
If HTTP promise is not completed, an HTTP promise completion event is written, equivalent to writing an HTTP Promise.then (callback), which executes promise when HTTP callback is complete Settledat Update all Promise array
Subscribe (promise, Undefined, function (value) {
Return Enumerator._settledat (fulfilled, I, value);
All/spread is just a simple encapsulation, the batch code is in the enumerator object, the bottom of all is enumerator.
So all check waits for all HTTP promise to complete, get each HTTP Response/value, then Resovle itself promise, pass the array, execute then inside
The Callback,callback entry parameter is an array, in the order in which the all array is written, not per HTTP, because the HTTP procedure is asynchronous and completes
The order is random. The way to wait is to use the event mechanism, with the Subscriber () method, equivalent to write then, each HTTP promise originally did not write Then,all
For each HTTP promise write a then, each HTTP promise completes after the update all array and determine whether all completed, if all is done after the execution of the
Then
In addition, Interceptormanager is to build a handlers[], by invoking the use of the custom interception function can be stored inside.
Axios Bottom is called XMLHttpRequest, that is, add the package, so easier to write, more convenient to use, equivalent to angular HTTP encapsulation, webuploader the bottom is also, but Webuploader is an application function,
It's more than just encapsulating the HTTP.
Analysis on key difficulties of Axios source code