Quote: Axios is often used in projects, but I was asked to wrap Ajax in AXIos form in an interview, which I didn’t write down. It seems that still can not stay on the surface of use. It is not difficult to come back to study promise. The key is to master promise A+ specification and promise writing. Let’s see how Axios implements this.
Axios source code:
I, Axios, am a Promise based HTTP client for the browser and Node.js.
Let’s focus on the Ajax section I want to learn about.
Adapters module in AXIOS
The modules under adapters/ are modules that handle dispatching a request and settling a returned Promise once a response is received. This module mainly handles distribution requests and processes them once a response to a returned Promise has been received.
In the source view: axios/lib/adapters/XHR. Js one let me shine at the moment:
module.exports = function xhrAdapter(config) {
return new Promise(function dispatchXhrRequest(resolve, reject) {})}Copy the code
We found the Promise base! Open, onReadyStatechange, send, etc.
/ / = >... omit config...
// step1=>
var request = new XMLHttpRequest();
// step2=>
request.open(config.method.toUpperCase(), buildURL(config.url, config.params, config.paramsSerializer), true);
// step3=>
request.onreadystatechange = function handleLoad() {
if(! request || request.readyState ! = =4) {
return;
}
// The request errored out and we didn't get a response, this will be
// handled by onerror instead
// With one exception: request that using file: protocol, most browsers
// will return status as 0 even though it's a successful request
if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') = = =0)) {
return;
}
// Prepare the response
var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;
varresponseData = ! config.responseType || config.responseType ==='text' ? request.responseText : request.response;
var response = {
data: responseData,
status: request.status,
statusText: request.statusText,
headers: responseHeaders,
config: config,
request: request
};
settle(resolve, reject, response);
// Clean up request
request = null;
};
/ / = >... omit handle process...
// step4=>
request.send(requestData);
Copy the code
This is just an ajax implementation, but the core then chain call is not implemented. The real implementation is to use axios/lib/core/settle.
/**
* 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.
*/
module.exports = function settle(resolve, reject, response) {
var validateStatus = response.config.validateStatus;
if(! validateStatus || validateStatus(response.status)) { resolve(response); }else {
reject(createError(
'Request failed with status code ' + response.status,
response.config,
null, response.request, response )); }};Copy the code
Once critical resolve and Reject are resolved, follow the Promise A+ specification
A promise must provide then methods to access its current or final value or cause.
Then (onFulfilled, onRejected), two of the methods can be used to process the return. The above has basically implemented ajax functions.
Following axios’s lead, encapsulate your own promise_Ajax
Initial implementation of your own P_ajax
function pajax({
url= null,
method = 'GET',
dataType = 'JSON',
async = true}){
return new Promise((resolve, reject) = > {
let xhr = new XMLHttpRequest()
xhr.open(method, url, async)
xhr.responseType = dataType
xhr.onreadystatechange = (a)= > {
if(!/^[23]\d{2}$/.test(xhr.status)) return
if(xhr.readyState === 4) {
let result = xhr.responseText
resolve(result)
}
}
xhr.onerror = (err) = > {
reject(err)
}
xhr.send()
})
}
Copy the code
JSON format is called by default and the test succeeds
ajax({
url:'./test.json'.method: 'get'
}).then((result) = >{
console.log(result)
},(err)=>{
})
Copy the code
Upgrade to optimize
For different request types, file types, do different processing
- Cache false indicates that the cache is not set. The simplest solution is to add _*** to the cache. *** is a random number
// Check whether the request type is GET
let isGet = /^(GET|DELETE|HEAD)$/i.test(method)
// Check whether the url exists. , add & if there is
let symbol = url.indexOf('? ') >- 1 ? '&' : '? '
// GET requests are processed in the cache
if(isGet){ ! cache ? url+=`${symbol}_The ${Math.random()}`: null
}
Copy the code
- Result is treated differently depending on the return type
let result = xhr.responseText
// Process the returned content according to dataType, i.e., different file types
switch(this.dataType.toUpperCase()){
case 'TEXT':
case 'HTML':
break;
case 'JSON':
result = JSON.parse(result)
break;
case 'XML':
result = xhr.responseXML
}
Copy the code
- When data is an object, it is converted to STR, and the aspect GET requests passing parameters
function formatData(data){
if(Object.prototype.toString.call(data)==='[object Object]') {let obj = data
let str = ' '
for(let key in obj){
if(obj.hasOwnProperty(key)){
str+=`${key}=${obj[key]}& `}}// Remove the extra & at the end
str = str.replace(/&$/g.' ')
return str
}
}
if(data ! = =null){
data = formatData(data)
if(isGet){
url += symbol + data
data = null}}Copy the code
Simple test results:
pajax({
url:'./test.json'.method: 'get'.cache: false.data: {name:'jyn'.age:20
}
}).then((result) = >{
console.log(result)
},(err)=>{
console.log(err)
})
Copy the code
The operation result is: the Request URL: http://localhost:63342/june/HTTP_AJAX/test.json? _0. 6717612341262227? Name =jyn&age=20, and then method can also get file data. When cache is set to false, the cache is refreshed every time and the cache is retrieved 200.
And there you have it, simple Ajax based on Promise!
Author: Yanni Jia Nickname: rabbit very much Reference: axios source: https://github.com/axios/axios