First, the front-end network request concerns
In most cases, we only need to pay attention to the following points when initiating a network request at the front end:
- Pass in basic parameters (
url
, request method) - Request parameter, request parameter type
- Set request header
- How to Get Response
- Acquiring a response head, a response state and a response result
- exception handling
- Carry
cookie
Set up - Cross domain request
Second, the front-end network request way
-
form
Forms,ifream
Refresh page -
Ajax
-Founder of Asynchronous Network Requests -
jQuery
-An era -
fetch
–Ajax
The replacement of -
axios、request
Such as many open source libraries
III. Questions about Network Requests
-
Ajax
The emergence of the solved what problem - Native
Ajax
How to use -
jQuery
The network request method of -
fetch
The usage of the and pits - How to Use It Correctly
fetch
- How to choose the appropriate cross-domain approach
With the above problems and concerns, we will conduct a comprehensive analysis of several network requests.
Fourth, what problems have Ajax solved?
InAjax
Before it appeared,web
The program works like this:
The defects of this interaction are obvious. Any interaction with the server needs to refresh the page, and the user experience is very poor.Ajax
The emergence of the has solved this problem.Ajax
Full nameAsynchronous JavaScript + XML
(AsynchronousJavaScript
AndXML
)
UseAjax
, web applications can quickly present incremental updates on the user interface without reloading (refreshing) the entire page.
Ajax
It is not a new technology in itself, but is used to describe a technical scheme implemented by using a collection of existing technologies, the browser’sXMLHttpRequest
Is to achieveAjax
The most important objects (IE6
The following usesActiveXObject
)。
AlthoughX
InAjax
Chinese representativeXML
However, due toJSON
Many of the advantages of, for example, lighter weight and asJavascript
Part of the currentJSON
The usage ratio ofXML
More common.
V usage of native Ajax
The main analysis here isXMLHttpRequest
Object, the following is a basic use of it:
var xhr = new XMLHttpRequest();
xhr.open('post','www.xxx.com',true)
//Receive return value
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 ){
if(xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
console.log(xhr.responseText);
}
}
}
//Process request parameters
postData = {"name1":"value1","name2":"value2"};
postData = (function(value){
var dataString = "";
for(var key in value){
dataString += key+"="+value[key]+"&";
};
return dataString;
}(postData));
//Set request header
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
//exception handling
xhr.onerror = function() {
console.log('Network request failed')
}
//Cross-domain cookie
xhr.withCredentials = true;
//make a request
xhr.send(postData);
The following are respectively rightXMLHttpRequest
Analysis of functions, attributes and events commonly used by objects.
Function
open
Used to initialize a request, usage:
xhr.open(method, url, async);
-
method
: request method, such asget、post
-
url
: requestedurl
-
async
: Is it an asynchronous request
send
For sendingHTTP
Request, that is, after calling the methodHTTP
The request will only be sent out.
xhr.send(param)
-
param
: Parameters for http requests, which can bestring、Blob
Equal type.
abort
Used to terminate oneajax
Request, after calling this methodreadyState
Will be set to0
, usage:
xhr.abort()
setRequestHeader
For settingHTTP
Request header, this method must be inopen()
Methods andsend()
Call between, usage:
xhr.setRequestHeader(header, value);
getResponseHeader
For obtaininghttp
Return header. If there are multiple identical names in the return header, the returned value will be a string separated by commas and spaces. Usage:
var header = xhr.getResponseHeader(name);
Attribute
readyState
Used to identify the currentXMLHttpRequest
The state of the object,XMLHttpRequest
The object is always in one of the following states:
value | state | describe |
---|---|---|
0 | UNSENT |
The proxy was created but has not been calledopen() Methods. |
1 | OPENED |
open() The method has already been called. |
2 | HEADERS_RECEIVED |
send() The method has been called and the header and state are already available. |
3 | LOADING |
Downloading;responseText Property already contains some data. |
4 | DONE |
Download operation completed. |
status
showhttp
The status of the request, with an initial value of0
. If the server does not explicitly specify a status code, thenstatus
Will be set to the default value, i.e.200
.
responseType
Indicates the data type of the response and allows us to set it manually. If it is empty, the default istext
Type, can have the following values:
value | describe |
---|---|
"" |
willresponseType Set to empty string and set to"text" Same, is the default type (actuallyDOMString )。 |
"arraybuffer" |
response Is a containing binary dataJavaScript ArrayBuffer . |
"blob" |
response Is a containing binary dataBlob Object. |
"document" |
Response is aHTML Document OrXML XMLDocument Depending on the MIME type of data received. |
"json" |
response Is a JavaScript object. This object is created by treating the received data type asJSON From the analysis. |
"text" |
response Is contained inDOMString The text in the object. |
response
Returns the body of the response, the type returned by the aboveresponseType
Decision.
withCredentials
ajax
The request will carry a homologous request by defaultcookie
While cross-domain requests are not carriedcookie
, settingsxhr
ThewithCredentials
The property of istrue
Cross-domain portability will be allowedcookie
.
Event callback
onreadystatechange
xhr.onreadystatechange = callback;
WhenreadyState
Callback is triggered when the property changes.
onloadstart
xhr.onloadstart = callback;
Inajax
Before the request is sent (readyState==1
After that,readyState==2
Before),callback
Will be triggered.
onprogress
xhr.onprogress = function(event){
console.log(event.loaded / event.total);
}
The callback function can obtain the total size of the resourcetotal
, the size of the loaded resourceloaded
With these two values, the loading progress can be calculated.
onload
xhr.onload = callback;
Triggered when a resource and its dependent resources have finished loadingcallback
, usually we will be inonload
The return value is processed in the event.
exception handling
onerror
xhr.onerror = callback;
Whenajax
Triggered when a resource fails to loadcallback
.
ontimeout
xhr.ontimeout = callback;
Triggered when progress is terminated due to expiration of the scheduled timecallback
, timeout can be usedtimeout
Property.
Six, jQuery Encapsulation of Ajax
For a long time, people usedjQuery
Providedajax
Encapsulating for network request, including$.ajax、$.get、$.post
Wait, I still think these methods are very practical now.
$.ajax({
DataType: 'json', // Sets the return value type
ContentType:' Application/JSON',//Set Parameter Type
Headers: {'content-type',' application/JSON'},//set request headers
Xhrfields: {with credentials: true},//cross-domain cookie
Data: JSON. stringify ({a: [{b: 1, a: 1}]}),//pass parameters
Error:function(xhr,status){ // error handling
console.log(xhr,status);
},
Success: function (data, status) {//get results
console.log(data,status);
}
})
$.ajax
Only one parameter is received, which receives a series of configurations and encapsulates one of its ownjqXHR
Object, you can read it if you are interested.JQuary-ajax source code
Common configurations:
url
Current page address. The address from which the request was sent.
type
Type:String
Request mode ("POST"
Or"GET"
), the default is"GET"
. Note: OtherHTTP
Request methods such asPUT
AndDELETE
It can also be used, but only some browsers support it.
timeout
Type:Number
Set the request timeout (milliseconds). This setting overrides the global setting.
success
Type:Function
Callback function after successful request.
jsonp
In onejsonp
Rewrite the name of the callback function in the request. This value is used instead of"callback=?"
suchGET
OrPOST
In requestURL
Of the parameters"callback"
Part of it.
errorType:Function
. This function is called when the request fails.
Note: Error judgment in source code:
isSuccess = status >= 200 && status < 300 || status === 304;
The return value will enter in addition to these status codes.error
Callback.
dataType
"xml": returns an XML document that can be processed by jQuery.
"html": return plain text HTML information; Contains script tags that are executed when dom is inserted.
"script": returns plain text JavaScript code. Results will not be cached automatically. Unless the "cache" parameter is set. Note: When a remote request is made (not under the same domain), all POST requests will be converted to GET requests. (because DOM's script tag will be used to load)
"json": returns JSON data.
"jsonp": JSONP format. When a function is called in JSONP form, such as "myurl? callback=?" JQuery will be replaced automatically? Is the correct function name to execute the callback function.
"text": Returns a plain text string
data
Type:String
UseJSON.stringify
Transcoding
complete
Type:Function
Callback function after completion of request (called after success or failure of request).
async
Type:Boolean
Default value:true
. By default, all requests are asynchronous. If you need to send a synchronization request, set this option tofalse
.
contentType
Type:String
Default value:"application/x-www-form-urlencoded"
. Content encoding type when sending information to server.
There is no problem with such an organization of key-value pairs under normal circumstances. What is said here is that there is no nested type.JSON
, that is, simpleJSON
, shaped like this:
{
a: 1,
b: 2,
c: 3
}
But there are problems in some complicated situations. For example, inAjax
You are going to pass on a complicatedjson
For example, it is said to be an array of embedded objects. The array includes objects. You pass it like this:application/x-www-form-urlencoded
There is no way for this form to be complicatedJSON
Organized into key-value pairs.
{
data: {
a: [{
x: 2
}]
}
}
Complexjson
Object
$.ajax({
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify({a: [{b:1, a:1}]})
})
Seven, jQuery’s replacement
In recent years, the front endMV*
With the development and expansion of, people are using it less and less.jQuery
We cannot use it alonejQuery
TheAjax api
To introduce him alone, inevitably, we need to find new technical solutions.
Evan You recommended it in his document.axios
Make a network request.axios
Based onPromise
For nativeXHR
It is fully packaged and used in a very elegant way. In addition,axios
Also provided innode
Support under the environment is the preferred solution for network requests.
There will definitely be better packaging in the future. They have very thorough consideration and detailed documents. We don’t do much research here. We focus on the lower API.fetch
.
Fetch API
Is a powerful native API for accessing and manipulating HTTP pipes.
This function was previously implemented using XMLHttpRequest. Fetch provides a better alternative and can be easily used by other technologies, such as Service Workers. Fetch also provides a single logical location to define other HTTP-related concepts, such as CORS and HTTP extensions.
Visiblefetch
Yes asXMLHttpRequest
For the first time.
Usefetch
, you don’t need to load an additional external resource. But it is not yet fully supported by browsers, so you still need onepolyfill
.
VIII. Use of fetch
A basic fetch request:
const options = {
Method: "POST", // request parameters
Headers: {"content-type": "application/JSON"},//set request header
Body: JSON. stringfy ({name:' 123'}),//request parameters
Credentials: "same-origin",//cookie settings
Mode: "cors", // Cross-domain
}
fetch('http://www.xxx.com',options)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson); //response data
})
.catch(function(err){
console.log(err); //exception handling
})
Fetch API
Provides a globalfetch()
Method and several auxiliary objects to initiate a network request.
fetch()
fetch()
The method is used to initiate a request to acquire resources. It returns apromise
Thispromise
After the request response is receivedresolve
And returnsResponse
Object.
Headers
ThroughHeaders()
Constructor to create your ownheaders
Object, equivalent toresponse/request
The header information can enable you to query the header information or do different operations for different results.
var myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
Request
viaRequest()
The constructor can create aRequest
Object that can be used as afetch
The second argument of the function.
Response
Infetch()
Finish processingpromises
Then return oneResponse
Instance, you can also create one manuallyResponse
Examples.
Nine, fetch polyfill source code analysis
Due tofetch
Is a very low levelAPI
, so we can’t further explore its underlying, but we can use itpolyfill
Explore its basic principles and find out the pits.
Code structure
As can be seen from the code,polyfill
Mainly toFetch
Four objects provided by API are encapsulated:
Fetch package
The code is very clear:
- Construct a
Promise
Object and returns - Create a
Request
Object - Create a
XMLHttpRequest
Object - Take out
Request
Request in objecturl
, the requesting party sends,open
Onexhr
Request and willRequest
Object stored in theheaders
Take out the assignment to xhr -
xhr onload
Take out afterresponse
Thestatus
、headers
、body
EncapsulationResponse
Object, callingresolve
.
exception handling
As you can see, callingreject
There are three possibilities:
- 1. The request timed out
- 2. The request failed
Note: when establishing a brief introduction with the server and receiving the abnormal status code of the server, such as404、500
Wait does not triggeronerror
. Only when the network fails or the request is blocked will it be marked asreject
, such as cross domain,url
Does not exist, network anomaly, etc. will triggeronerror
.
Therefore, fetch will enter then instead of catch when receiving abnormal status codes. These erroneous requests are often handled manually.
- 3. Manual termination
Can be found inrequest
Incoming parameterssignal
Object, and tosignal
Object additionabort
Event monitoring, whenxhr.readyState
become4
(Response Content Parsing Completed) Remove abort Event Monitoring of signal Object.
This means that in onefetch
You can call before the request ends.signal.abort
Terminate it. Can be used in the browserAbortController()
The constructor creates a controller and then uses theAbortController.signal
Attribute
This is an experimental function. Some browsers for this function are still under development.
Headers package
One is maintained in the header objectmap
Object that can be passed into the constructorHeader
Object, array, common object typeheader
And maintain all values tomap
China.
Beforefetch
The call is seen in the functionheader
TheforEach
Method, the following is its implementation:
Visibleheader
The traversal of is its interiormap
The traversal of the.
In additionHeader
Also provided areappend、delete、get、set
Such as method, are internal to itmap
Object.
collectionlpropertylmethod] variable
Request
The two parameters that the object receives arefetch
Function receives two parameters, the first parameter can be passed directlyurl
You can also pass a constructedrequest
Object. The second parameter controls different configurationsoption
Object.
Can be passed incredentials、headers、method、mode、signal、referrer
Equal attribute.
Note here:
- incident
headers
Be treated asHeaders
Constructor to construct a header object.
Cookie processing
The fetch function also has the following code:
if (request.credentials === 'include') {
xhr.withCredentials = true
} else if (request.credentials === 'omit') {
xhr.withCredentials = false
}
Defaultcredentials
Type issame-origin
, you can carry the coodkie of the same origin request.
Then I found out that the implementation of polyfill here andMDN- use FetchAnd a lot of data are inconsistent:
Mdn: By default, fetch will not send or receive any cookies from the server.
So I tested the next use separatelypolyfill
And the use of nativefetch
The case of carrying a cookie is found in not settingcredentials
Under the condition of incredibly are carrying homologous by defaultcookie
Yes, this is not consistent with the description in the document. After consulting many materials, it is said thatfetch
Cookie will not be carried by default, the following is the use of nativefetch
When the browser makes a request:
And then I found out that inMDN-Fetch-RequestA new version of the browser has been pointed out.credentials
The default value has been changed tosame-origin
, the old version is stillomit
.
IndeedMDN- use FetchSome of the documents here are not updated in time, which is misleading. …
Response object
Response
The object isfetch
Return value after successful call:
Looking backf
etchRight
Action for Response’:
xhr.onload = function () {
var options = {
status: xhr.status,
statusText: xhr.statusText,
headers: parseHeaders(xhr.getAllResponseHeaders() || '')
}
options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
var body = 'response' in xhr ? xhr.response : xhr.responseText
resolve(new Response(body, options))
}
Response
Constructor:
It can be seen that in the constructor the main pairoptions
hit the targetstatus、statusText、headers、url
After being processed and mounted to theResponse
Object.
There is no pair in the constructorresponseText
Clear processing, finally handed over to the_initBody
Function processing, whileResponse
There is no voluntary statement_initBody
Property, code last usedResponse
CalledBody
Function, in fact_initBody
The function passes throughBody
The function is mounted to theResponse
Take a look at what’s on your body first._initBody
Functions:
Obviously,_initBody
Function basisxhr.response
Type of (Blob、FormData、String ...
To assign values to different parametersBody
The method has been applied in different ways. Let’s take a look at it in detail.Body
What other operations did the function do?
Body
Function is alsoResponse
The object mounts four functions,text、json、blob、formData
The operation in these functions is to return different types of return values obtained in _initBody.
This also shows that infetch
After the completion of the implementation, not directly inresponse
Must be called to get the return value fromtext()、json()
Wait for the function to get the return value.
There is another point to be made here: several functions have logic similar to the following:
var rejected = consumed(this)
if (rejected) {
return rejected
}
Consumed function:
function consumed(body) {
if (body.bodyUsed) {
return Promise.reject(new TypeError('Already read'))
}
body.bodyUsed = true
}
Every calltext()、json()
After waiting for the function, thebodyUsed
Variable becomestrue
, used to identify the return value has been read, the next read directly thrownTypeError('Already read')
. This also follows the originalfetch
The principle of:
Because the Responses objects are set to the stream mode, they can only be read once.
Ten, fetch pit
VUE
The rightfetch
There is the following description:
Use
fetch
There are many other matters needing attention, which is why everyone still prefers it at this stage.axios
More. Of course, this matter may change in the future.
Due tofetch
Is a very low levelAPI
, it has not been packaged in many ways, and there are still many problems to deal with:
- Not directly delivered
JavaScript
Object as parameter - You need to judge the type of return value and execute the method of obtaining the return value in response.
- The method to get the return value can only be called once, not many times.
- Unable to normally capture exception
- The old browser will not be carried by default.
cookie
- nonsupport
jsonp
XI. Packaging fetch
Request parameter processing
Different parameter types can be passed in:
function stringify(url, data) {
var dataString = url.indexOf('?' ) == -1 ? '?' : '&';
for (var key in data) {
dataString += key + '=' + data[key] + '&';
};
return dataString;
}
if (request.formData) {
request.body = request.data;
} else if (/^get$/i.test(request.method)) {
request.url = `${request.url}${stringify(request.url, request.data)}`;
} else if (request.form) {
request.headers.set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.body = stringify(request.data);
} else {
request.headers.set('Content-Type', 'application/json; charset=UTF-8');
request.body = JSON.stringify(request.data);
}
Cookie carrying
fetch
In the new version of the browser has begun to carry homologous defaultcookie
However, it will not be carried by default in the old browser. We need to set it uniformly:
request.credentials = 'same-origin'; //homologous carrying
request.credentials = 'include'; //can be carried across domains
exception handling
When an HTTP status code representing an error is received, the Promise returned from fetch () will not be marked reject, even if the status code of the HTTP response is 404 or 500. Instead, it marks the Promise status as resolve (but sets the ok attribute of the return value of resolve to false) and will mark reject only when the network fails or the request is blocked.
So we have to be rightfetch
The exception of the unified processing
.then(response => {
if (response.ok) {
return Promise.resolve(response);
}else{
Const error = new Error (`request failed! Status code: ${response.status}, failure information: ${response.statusText} `;
error.response = response;
return Promise.reject(error);
}
});
Return value processing
Call different functions to receive different return value types. You must judge the type in advance and cannot call the method to obtain the return value many times:
.then(response => {
let contentType = response.headers.get('content-type');
if (contentType.includes('application/json')) {
return response.json();
} else {
return response.text();
}
});
jsonp
fetch
It does not provide the rightjsonp
The support of,jsonp
It does not belong to a very good way to solve cross-domain problems. It is recommended to use it.cors
Or ..nginx
To solve cross-domain problems, please refer to the following sections.
Fetch is packaged and can be used happily.
Well, axios works really well. …
XII. Cross-domain Summary
When it comes to network requests, we have to mention cross-domain.
The browser’s homology policy restricts how documents or scripts loaded from the same source interact with resources from another source. This is an important security mechanism for isolating potentially malicious files. Read operations between different sources are generally not allowed.
Cross-domain condition: if there is a difference between protocol, domain name and port, cross-domain is considered.
Here are some ways to solve cross-domain problems:
nginx
Usenginx
Reverse proxy implements cross-domain, refer to my article:Nginx knowledge for front-end developers
cors
CORS
Is aW3C
Standard, full name is “cross-domain resource sharing”(Cross-origin resource sharing)
. It allows browsers to sendXMLHttpRequest
Request.
Server settingsAccess-Control-Allow-Origin
Can be openedCORS
. This attribute indicates which domain names can access resources, and if wildcards are set, all websites can access resources.
app.all('*', function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
next();
});
jsonp
script
Taggedsrc
Links in the property can access cross-domainjs
Script, using this feature, the server will not return any moreJSON
Format of data, but return a call to a functionjs
Code, insrc
In this way, cross-domain is realized.
jquery
Yesjsonp
Support for:
$.ajax({
type : "get",
url : "http://xxxx"
dataType: "jsonp",
jsonp:"callback",
jsonpCallback: "doo",
success : function(data) {
console.log(data);
}
});
fetch、axios
Such as did not directly provide the rightjsonp
, if you need to use this method, we can try manual packaging:
(function (window,document) {
"use strict";
var jsonp = function (url,data,callback) {
// 1. Convert the incoming data data into url string form
// {id:1,name:'jack'} => id=1&name=jack
var dataString = url.indexof('?' ) == -1? '?' : '&';
for(var key in data){
dataString += key + '=' + data[key] + '&';
};
// 2 Handle callback function in url
//name of cbfuncname callback function: prefix of my_json_cb_ name+random number (decimal point removed)
var cbFuncName = 'my_json_cb_' + Math.random().toString().replace('.','');
dataString += 'callback=' + cbFuncName;
// 3. Create a script tag and insert it into the page
var scriptEle = document.createElement('script');
scriptEle.src = url + dataString;
// 4. Mount callback function
window[cbFuncName] = function (data) {
callback(data);
//After processing the data of the callback function, delete the script tag of jsonp
document.body.removeChild(scriptEle);
}
document.body.appendChild(scriptEle);
}
window.$jsonp = jsonp;
})(window,document)
PostMessage cross-domain
postMessage()
The method allows scripts from different sources to carry out limited communication in an asynchronous manner, and can realize cross-text file, multi-window and cross-domain message transmission.
//capture iframe
var domain = 'http://scriptandstyle.com';
var iframe = document.getElementById('myIFrame').contentWindow;
//Send message
setInterval(function(){
var message = 'Hello! The time is: ' + (new Date().getTime());
console.log('blog.local: sending message: ' + message);
//send the message and target URI
iframe.postMessage(message,domain);
},6000);
//Response Event
window.addEventListener('message',function(event) {
if(event.origin ! == 'http://davidwalsh.name') return;
console.log('message received: ' + event.data,event);
event.source.postMessage('holla back youngin!' ,event.origin);
},false);
postMessage
Cross-domain is applicable to the following scenarios: cross-domain communication between multiple windows with browser,iframe
Inter-domain communication.
WebSocket
WebSocket
It is a two-way communication protocol. After the connection is established,WebSocket
Theserver
Andclient
Can actively send or receive data to each other without being limited by homologous policies.
function WebSocketTest(){
if ("WebSocket" in window){
Alert ("your browser supports WebSocket!" );
//open a web socket
var ws = new WebSocket("ws://localhost:3000/abcd");
ws.onopen = function(){
// Web Socket is connected, and send () method is used to send data
Ws.send ("sending data");
Alert ("in data transmission ...");
};
ws.onmessage = function (evt) {
var received_msg = evt.data;
Alert ("Data Received ...");
};
ws.onclose = function(){
//close websocket
Alert ("Connection Closed ...");
};
} else{
//the browser does not support WebSocket.
Alert ("your browser does not support WebSocket!" );
}
}
If there are any mistakes in the article, please correct them in the comment area. Thank you for reading.
Recommended for everyoneFundebug, a very useful BUG monitoring tool ~