Detailed AJAX


foreword

提示:本文主要解决的问题:

  1. How to create xmlHttpRequest object?
  2. How to transfer data through get and post?
  3. How to control http header information?
  4. What format data can be passed through ajax?
  5. How to receive the data delivered by the server?
  6. How to control the progress of data reception?
  7. How to control errors during data transfer?
  8. Questions about cross transfers?

1 Ajax technology and principle

1.1 Introduction to Ajax

a. What is AJAX?

  • AJAX = Asynchronous JavaScript and XML (Asynchronous JavaScript and XML)
  • AJAX is not a new programming language, but a new way of using existing standards
  • AJAX is the art of exchanging data with a server and updating parts of a web page without reloading the entire page

Although the x in Ajax stands for XML, many advantages of JSON are now more commonly used than XML.

Both JSON and XML are used to encapsulate data in Ajax models

b. Asynchronous interaction and synchronous interaction

  • Synchronization :
    (1) To send a request, you must wait for the end of the server's response before sending a second request
    (2) This page is refreshed

  • Asynchronous :
    (1) After sending a request, there is no need to wait for the server's response, and then the second request can be sent
    (2) You can use the js interface server's response, and then use js to partially refresh
    insert image description here

c. Disadvantages of asynchronous interaction and synchronous interaction :

  • Breaks the browser's forward and backward mechanism
  • When the latter logic depends on the previous logic, problems may arise
  • Ajax has weak support for search engines
  • It is easy to cause web security problems

1.2 Technologies included in Ajax

Ajax is not a new technology, but an integration of multiple technologies:

  • HTML
  • CSS
  • JavaScript
  • DOM
  • XML
  • XMLHttpRequest object

XMLHttpRequest is the heart of Ajax.

The XMLHttpRequest object provides the function of transmitting data between the client and the server. The XMLHttpRequest object provides the method of obtaining data through the URL, and only updates part of the data on the web page.

1.3 How Ajax works

The working principle of Ajax is equivalent to adding an intermediate layer (AJAX engine-JavaScript object) between the user and the server to make user operations and server responses asynchronous. Not all user requests are submitted to the server. Some data validation and data processing are left to the Ajax engine itself. Only when it is determined that new data needs to be read from the server will the Ajax engine submit a request to the server on its behalf.

The principle of Ajax is simply to send an asynchronous request to the server through the XmlHttpRequest object, obtain data from the server, and then use javascript to manipulate the DOM to update the page.

1.4 Three common attributes of XMLHttpRequest object

1. onreadystatechange attribute

The onreadystatechange attribute holds the function that handles the server's response.

xmlHttp.onreadystatechange = function() {
    
    
    //我们需要在这写一些代码

2. readyState property

The readyState property holds the status information of the server response. Whenever the readyState changes, the onreadystatechange function will be executed.

Possible values ​​for the readyState property:

value state describe
0 request uninitialized, UNSENT (unopened) open() method was not called
1 Request made, OPEN (not sent) send() method was not called
2 The request has been sent, HEADERS_PECEIVED (response headers have been obtained) send() method has been called
3 Request processing, LOADING (downloading response body) The response body is being downloaded; part of the data has been obtained in respnseText
4 The request has been completed, DOWN (request completed) The entire request process is complete

We're going to add an If statement to this onreadystatechange function to test if our response is complete (meaning data is available):

xmlHttp.onreadystatechange = function() {
    
    
    if (xmlHttp.readyState == 4) {
    
    
        //从服务器的response获得数据
    }
}

3. responseText attribute

The data (string) returned by the server can be retrieved through the responseText property.
In our code, we'll set the value of the time textbox equal to responseText:

xmlHttp.onreadystatechange = function() {
    
    
    if (xmlHttp.readyState == 4) {
    
    
        document.myForm.time.value = xmlHttp.responseText;
    }
}

Other properties:

Attributes describe
status HTTP status of the server
statusText The corresponding text of the HTTP status
responseXML The server's response, represented as XML, this object can be parsed as a DOM object

HTTP status of the server :
1**: Request received, continue processing (information class)
2**: Operation successfully received, analyzed, accepted (success class)
3**: This request must be further processed (redirection) to complete this request
4 **: The request contained an incorrect syntax or could not be completed (client error)
5**: The server failed to execute a perfectly valid request (server error)

Common status:
200——The server has successfully processed the request
400—(Bad request) The server does not understand the syntax of the request
401—Indicates that the request sent requires authentication information through HTTP authentication
403——(Forbidden) The server rejects the request
404 - (Not found) The server could not find the requested page
500 - (Server internal error) The server encountered an error and could not complete the request
503 - Indicates that the server is down for maintenance or overloaded and cannot process the request

1.5 The method of xmlhttprequst

method describe
abort() stop current request
getAllResponseHeaders() Return all corresponding headers of the HTTP request as key/value pairs.
getResponseHeader(“header”) Returns the string value of the specified header.
open(“method”,“url”) Make a call to the server. The method parameter can be GET, POST or PUT, etc.; the url parameter can be a relative URL or an absolute URL. This method also includes 3 optional parameters.
send(content) Send a request to the server.
setRequestHeader(“header”,“value”) Sets the specified header to the provided value. The open() method must be called before setting any headers.

1. open() method

Make a call to the server.

Open() method syntax structure:

open(method, url[, async, user, password])

Parameter Description:

  • method: request method, get, post, put, delete, etc.
  • url: the url to send the request
  • async: Whether to interact asynchronously
  • user: username for authentication purposes
  • password: user password

2. send() method

The send() method sends the request to the server.

send([body])

body: the data body to send in the XHR request, or null if no data is passed

If you use the GET request to send data, you need to pay attention to the following:

  • Add the request data to the url address in the open() method
  • The parameter in the send() method in sending request data is set to null

When the send() method is called, it is used to send data, the default is asynchronous sending, and returns immediately after sending;
if it is synchronous sending, it returns after waiting for a response. The send method does not pass in parameters, which means that no data is sent. When the request method is get or head, the body needs to be set to null.

Two Ajax programming steps

2.1 Create XMLHttpRequest object

The XMLHttpRequest() constructor is used to initialize an XMLHttpRequest instance object

const xhr = new XMLHttpRequest();

If it is IE5 or IE6 browser, use the ActiveX object, the creation method is:

var xhr=new ActiveXObject("Microsoft.XMLHTTP");

Generally, when we write AJAX by hand, we must first determine whether the browser supports the XMLHttpRequest object, if it supports it, create the object, and if it does not support it, create the ActiveX object. The JS code is as follows:

//第一步:创建XMLHttpRequest对象
var xmlHttp;
if (window.XMLHttpRequest) {
    
                //非IE
    xmlHttp = new XMLHttpRequest();
} else if (window.ActiveXObject) {
    
           //IE
    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP")
}

2.2 Set the request method

Establish a connection with the server through the open() method of the XMLHttpRequest object

//第二步:设置和服务器端交互的相应参数
xhr.open(method, url, [async][, user][, password])

2.3 Call callback function

If the third parameter of the open method is true in the previous step, then the current request is an asynchronous request. At this time, a callback function needs to be written. The XMLHttpRequest object has an onreadystatechange attribute, which returns an anonymous method, so the callback The function is written here xmlHttp.onreadystatechange=function{}, and inside function{} is the content of the callback function.

//第三步:注册回调函数
xhr.onreadystatechange = function() {
    
    
    if (xhr.readyState == 4 && xhr.status == 200) {
    
    
            var obj = document.getElementById(id);
            obj.innerHTML = xhr.responseText;
        } else {
    
    
            alert("AJAX服务器返回错误!");
        }
    }
}

2.4 Send request

Send the data of the client page to the server through the send() method of the XMLHttpRequest object

xhr.send([body])

3. Application examples

3.1 ajax package

Through the understanding of the XMLHttpRequest object, let's encapsulate a simple ajax request

//封装一个ajax请求
function ajax(options) {
    
    
    //创建XMLHttpRequest对象
    const xhr = new XMLHttpRequest()
 
 
    //初始化参数的内容
    options = options || {
    
    }
    options.type = (options.type || 'GET').toUpperCase()
    options.dataType = options.dataType || 'json'
    const params = options.data
 
    //发送请求
    if (options.type === 'GET') {
    
    
        xhr.open('GET', options.url + '?' + params, true)
        xhr.send(null)
    } else if (options.type === 'POST') {
    
    
        xhr.open('POST', options.url, true)
        xhr.send(params)
 
    //接收请求
    xhr.onreadystatechange = function () {
    
    
        if (xhr.readyState === 4) {
    
    
            let status = xhr.status
            if (status >= 200 && status < 300) {
    
    
                options.success && options.success(xhr.responseText, xhr.responseXML)
            } else {
    
    
                options.fail && options.fail(status)
            }
        }
    }
}

Use as follows

ajax({
    
    
    type: 'post',
    dataType: 'json',
    data: {
    
    },
    url: 'https://xxxx',
    success: function(text,xml){
    
    //请求成功后的回调函数
        console.log(text)
    },
    fail: function(status){
    
    请求失败后的回调函数
        console.log(status)
    }
})

3.2 ajax progress control

Brief description of progress bar events

  • loadstart: Triggered when the first byte of the corresponding data is received.
  • progress: Triggered continuously during the acceptance of the response, this event is executed about every 50 milliseconds.
  • error: Triggered when the request sends an error
  • abort: Triggered when the connection is terminated due to calling the abort() method
  • load: Triggered when the complete corresponding data is received
  • loadend: start after the communication is completed or an error, abort or load event is triggered
  • timeout: If a timeout value is specified, it will be triggered when the request is not completed within the specified time period.

Example of a progress bar :

<meta charset="utf-8">
<script type="text/javascript">
Object.prototype.addListener=function(ev,fn){
    
    
    if (this.attachEvent) {
    
    
        this.attachEvent('on' + ev, fn);
    }else{
    
     
        this.addEventListener(ev,fn,false);
    }
}
function CreateXmlHttp() {
    
    
    if (window.XMLHttpRequest)
    {
    
    // code for IE7+, Firefox, Chrome, Opera, Safari
      xmlhttp=new XMLHttpRequest();
    }else{
    
    // code for IE6, IE5
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }    
}
var xmlhttp=null;
window.onload=function(){
    
    
    var loadbutton=document.getElementById('loadbutton');
    loadbutton.addListener('click',function(){
    
    
        CreateXmlHttp();//创建xmlHttpRequest对象
        //绑定事件,是我addListener自定义兼容各浏览器的绑定事件方法
        xmlhttp.addListener('loadstart',loadstart);
        xmlhttp.addListener('progress',progress);
        xmlhttp.addListener('load',load);
        xmlhttp.addListener('loadend',function(){
    
    console.log('执行结束了');});
        xmlhttp.open("get", "http://127.0.0.1/ceshi.pdf", true);//调用open的方法初始化(为了便于查看效果,我让其加载一个比较大的文件,因为最开始,我尝试使用一个php文件但是看不到效果,因为它立刻出现结果)
        xmlhttp.send();//调用send方法发送数据
    }); 
}
//处理开始接受数据的画面
function loadstart(){
    
    
    //当开始加载的时候,将defaultCont隐藏,将progressBox显示出来
    document.getElementById('defaultCont').style.display="none";
    document.getElementById('progressBox').style.display="block";
}
//处理进度
function progress(event){
    
    
    //修改progressTest里面的文本提示信息以及progress的长度
    var progressTest=document.getElementById('progressTest');
    var progress=document.getElementById('progress');
    if (event.lengthComputable) {
    
    //判断响应文本是否可以计算长度
        var recivedSize= event.position;//已经接收的字节数
        var totalSize=event.totalSize;//根据Content-Length相应头部确定的预期字节数
        progressTest.innerText=(recivedSize/totalSize*100 )+"%";
        progress.style.width=600*(recivedSize/totalSize)+"px";// 为什么是600,因为包含它的容器长度为600
    }
}
//处理加载完成
function load(event){
    
    
    //当开始加载的时候,将defaultCont显示出来,并将服务器返回的结果放在其里面,并将progressBox隐藏掉
    document.getElementById('progressBox').style.display="none";
    var defaultCont=document.getElementById('defaultCont')
    defaultCont.style.display="block";  
    //因为加载的是一个pdf文件,所以不需要将其显示在页面上,我直接输出了xmlhttp对象
    console.log(event.target);
    //defaultCont.innerText=event.target.responseText;//备注,其中event.target为xmlhttp对象 
    //使用innerText代替innerHTML更加安全,因为如果使用innerHTML,responseText中包含html代码或JavaScript代码时候,浏览器不会解析,如果你需要其解析,当然得用innerHTML。
}
</script>
<div style="width:600px; height:auto;margin:0 auto">
    <input type="button" id="loadbutton" value="加载">
    <div id="defaultCont">
        <img src="1.jpg" width="600px">
    </div>
    <div id="progressBox" style="display:none;position:relative">
        <div>已经加载了:<span id="progressTest">0</span></div>
        <div id="progress" style="position:absolute; width:0px; top:35px; left:0;z-index:10; height:35px; background-color:#F00"></div>
        <div style="position:absolute; width:600px; top:35px; left:0; z-index:1;height:35px; background-color:#040"></div>
    </div>
</div>

3.3 ajax cross domain control

1. What is cross domain**

The full name of CORS is Cross-Origin Resource Sharing, which means cross-domain resource sharing. When a resource accesses another resource with a different domain name or a different port with the same domain name, a cross-domain request is issued. If another resource does not allow it to access cross-domain resources at this time, then the access will encounter cross-domain problems.

Cross-domain means that browsers cannot execute scripts from other websites. It is caused by the browser's same-origin policy, which is a security restriction imposed by the browser on JavaScript.

2. What is the same-origin policy**

The same origin policy (Same origin policy) is a convention, which is the core and most basic security function of the browser. If the same origin policy is missing, the normal functions of the browser may be affected. It can be said that the Web is built on the basis of the same-origin policy, and the browser is only an implementation of the same-origin policy. The same-origin policy prevents javascript scripts from one domain from interacting with content from another domain.

The so-called same origin (that is, in the same domain) means that two pages have the same protocol (protocol), host (host) and port number (port)

The same-origin policy restricts the following behaviors:

  • Cookies, LocalStorage and IndexDB cannot be read
  • DOM and JS objects cannot be obtained
  • AJAX request could not be sent

Regulations: The browser requires that when parsing the Ajax request, the path of the browser and the path of the Ajax request must meet three requirements, then the same-origin policy is satisfied and the server can be accessed.

Requirement: two pages have the same protocol (protocol), host (host) and port number (port)

Web site (URL) :

Composition:
protocol://service domain name (IP: port)/URI?key1=value1&key2=value2#xxxx
or
protocol://service domain name (IP: port)/file name or directory (restful style)

  • Protocol: http, https, ftp...
  • Service: World Wide Web
  • Domain name = identification string (baidu, google, sina...) + website type (com, gov, edu...)
  • IP address:
  • Port number: expressed in digital form, if the protocol is HTTP, the default port number is 80, which can be omitted
  • URI: Uniform Resource Identifier (the specific address of a resource available on the Web)
  • Query: start with "?", separate each parameter with "&", and separate parameter name and data with "="
  • Snippets: start with a '#' character

3. Common cross-domain scenarios**

URL illustrate Whether to allow communication
Browser address
http://www.domain.com/a.js
Ajax request address 1
http://www.domain.com/b.js
Ajax request address 2
http://www.domain.com/lab/c .js
Same domain name, different files or paths allow
Browser address
http://www.domain.com:8000/a.js
Ajax request address
http://www.domain.com/b.js
Same domain name, different ports not allowed
Browser address
http://www.domain.com/a.js
Ajax request address
https://www.domain.com/b.js
Same domain name, different protocols not allowed
Browser address
http://www.domain.com/a.js
Ajax request address
http://192.168.4.12/b.js
The domain name and the domain name correspond to the same ip not allowed

4. Cross-domain solutions**

1. ajax jsonp

JSONP is a common method for cross-origin communication between servers and clients. The biggest feature is that it is simple and applicable, and has good compatibility (compatible with lower versions of IE). The disadvantage is that it only supports get requests and does not support post requests.

Core idea: The web page requests JSON data from the server by adding a <script> element. After receiving the request, the server puts the data in the parameter position of a callback function with a specified name and sends it back.

① Native implementation:

<script src="http://test.com/data.php?callback=dosomething"></script>
// 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
 
// 处理服务器返回回调函数的数据
<script type="text/javascript">
    function dosomething(res){
    
    
        // 处理获得的数据
        console.log(res.data)
    }
</script>

② jQuery ajax:

$.ajax({
    
    
    url: 'http://www.test.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // 请求方式为jsonp
    jsonpCallback: "handleCallback",    // 自定义回调函数名
    data: {
    
    }
});

③ Vue.js

this.$http.jsonp('http://www.domain2.com:8080/login', {
    
    
    params: {
    
    },
    jsonp: 'handleCallback'
}).then((res) => {
    
    
    console.log(res); 
})

2. CORS method

CORS (Cross-origin resource sharing) "Cross-origin resource sharing", now the mainstream browsers support the way of cors. If you need to cross-domain, you need to configure the response header information to identify whether it is allowed.

Classification:

  • Ordinary cross-domain requests: only need to set Access-Control-Allow-Origin on the server side
  • Cross-domain requests with cookies: Both the front and back ends need to be set

As long as the following two conditions are met at the same time, it is a simple request

(1) Use one of the following methods:

  • head
  • get
  • post

(2) The requested Heder is

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type: limited to three values: application/x-www-form-urlencoded, multipart/form-data, text/plain

If the above two conditions are not met at the same time, it is a non-simple request. Browsers treat these two differently.

a. Simple request

For simple requests, the browser makes a CORS request directly. Specifically, an Origin field is added to the header information.

GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

In the above header information, the Origin field is used to indicate which source (protocol + domain name + port) this request comes from. Based on this value, the server decides whether to agree to the request.

CORS请求设置的响应头字段,都以 Access-Control-开头:

1)Access-Control-Allow-Origin:必选

它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

2)Access-Control-Allow-Credentials:可选

它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

3)Access-Control-Expose-Headers:可选

CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader(‘FooBar’)可以返回FooBar字段的值。

b. 非简单请求

非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

预检请求

预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的。请求头信息里面,关键字段是Origin,表示请求来自哪个源。除了Origin字段,"预检"请求的头信息包括两个特殊字段。

GET /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0..

1)Access-Control-Request-Method:必选

用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。

2)Access-Control-Request-Headers:可选

该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header。

预检请求的回应

服务器收到"预检"请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。

HTTP回应中,除了关键的是Access-Control-Allow-Origin字段,其他CORS相关字段如下:

1)Access-Control-Allow-Methods:必选

它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

2)Access-Control-Allow-Headers

如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。

3)Access-Control-Allow-Credentials:可选

该字段与简单请求时的含义相同。

4)Access-Control-Max-Age:可选

用来指定本次预检请求的有效期,单位为秒。

CORS跨域示例

【前端设置】根据xhr.withCredentials字段判断是否带有cookie

① 原生ajax:

var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
 
// 前端设置是否带cookie
xhr.withCredentials = true;
 
xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
 
xhr.onreadystatechange = function() {
    
    
    if (xhr.readyState == 4 && xhr.status == 200) {
    
    
        alert(xhr.responseText);
    }
};

② jquery ajax:

$.ajax({
    
    
    ...
   xhrFields: {
    
    
       withCredentials: true    // 前端设置是否带cookie
   },
   crossDomain: true,   // 会让请求头中包含跨域的额外信息,但不会含cookie
    ...
});

③ vue-resource

Vue.http.options.credentials = true

④ axios

axios.defaults.withCredentials = true

【服务端设置】

服务器端对于CORS的支持,主要是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。

① Java后台

/*
 * 导入包:import javax.servlet.http.HttpServletResponse;
 * 接口参数中定义:HttpServletResponse response
 */
 
// 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/'
response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com"); 
 
// 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示
response.setHeader("Access-Control-Allow-Credentials", "true"); 
 
// 提示OPTIONS预检时,后端需要设置的两个常用自定义头
response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");

② nodejs代码

var http = require('http');
var server = http.createServer();
var qs = require('querystring');
 
server.on('request', function(req, res) {
    
    
    var postData = '';
 
    // 数据块接收中
    req.addListener('data', function(chunk) {
    
    
        postData += chunk;
    });
 
    // 数据接收完毕
    req.addListener('end', function() {
    
    
        postData = qs.parse(postData);
 
        // 跨域后台设置
        res.writeHead(200, {
    
    
            'Access-Control-Allow-Credentials': 'true',     // 后端允许发送Cookie
            'Access-Control-Allow-Origin': 'http://www.domain1.com',    // 允许访问的域(协议+域名+端口)
            /* 
             * 此处设置的cookie还是domain2的而非domain1,因为后端也不能跨域写cookie(nginx反向代理可以实现),
             * 但只要domain2中写入一次cookie认证,后面的跨域接口都能从domain2中获取cookie,从而实现所有的接口都能跨域访问
             */
            'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'  // HttpOnly的作用是让js无法读取cookie
        });
 
        res.write(JSON.stringify(postData));
        res.end();
    });
});
 
server.listen('8080');
console.log('Server is running at port 8080...');

③ PHP后台

<?php
 header("Access-Control-Allow-Origin:*");

④ Apache需要使用mod_headers模块来激活HTTP头的设置,它默认是激活的。你只需要在Apache配置文件的, , 或的配置里加入以下内容即可

Header set Access-Control-Allow-Origin *

3. 设置document.domain解决无法读取非同源网页的 Cookie问题

因为浏览器是通过document.domain属性来检查两个页面是否同源,因此只要通过设置相同的document.domain,两个页面就可以共享Cookie(此方案仅限主域相同,子域不同的跨域应用场景。)

// 两个页面都设置
document.domain = 'test.com';

4. 跨文档通信 API:window.postMessage()

postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:

它可用于解决以下方面的问题:

  • 页面和其打开的新窗口的数据传递
  • 多窗口之间消息传递
  • 页面与嵌套的iframe消息传递
  • 上面三个场景的跨域数据传递

用法:postMessage(data,origin)方法接受两个参数:

  • data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
  • origin: 协议+主机+端口号,也可以设置为"*“,表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为”/"。
// 父窗口打开一个子窗口
var openWindow = window.open('http://test2.com', 'title');
 
// 父窗口向子窗口发消息(第一个参数代表发送的内容,第二个参数代表接收消息窗口的url)
openWindow.postMessage('Nice to meet you!', 'http://test2.com');

调用message事件,监听对方发送的消息

// 监听 message 消息
window.addEventListener('message', function (e) {
    
    
  console.log(e.source); // e.source 发送消息的窗口
  console.log(e.origin); // e.origin 消息发向的网址
  console.log(e.data);   // e.data   发送的消息
},false);

5. webpack本地代理

insert image description here
在webpack.config.js中利用 WebpackDevServer 配置本地代理,详情配置查看devServer

如下简单配置案例,这样 http://localhost:8080/api/getUser.php 的请求就是后端的接口 http://192.168.25.20:8088/getUser.php

    devServer: {
    
    
        port: 8080,
        proxy: {
    
    
            "/api": {
    
    
              target: "http://192.168.25.20:8088" // 后端接口
            }
        }
    }

6. websocket

Websocket 是 HTML5 的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket 和 HTTP 都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 服务器与 客户端都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。

</script>
<script>
var socket = io('http://www.domain2.com:8080');
 
// 连接成功处理
socket.on('connect', function() {
    
    
    // 监听服务端消息
    socket.on('message', function(msg) {
    
    
        console.log('data from server: ---> ' + msg); 
    });
 
    // 监听服务端关闭
    socket.on('disconnect', function() {
    
     
        console.log('Server socket has closed.'); 
    });
});
 
document.getElementsByTagName('input')[0].onblur = function() {
    
    
    socket.send(this.value);
};
</script>

Nodejs socket后台:

var http = require('http');
var socket = require('socket.io');
 
// 启http服务
var server = http.createServer(function(req, res) {
    
    
    res.writeHead(200, {
    
    
        'Content-type': 'text/html'
    });
    res.end();
});
 
server.listen('8080');
console.log('Server is running at port 8080...');
 
// 监听socket连接
socket.listen(server).on('connection', function(client) {
    
    
    // 接收信息
    client.on('message', function(msg) {
    
    
        client.send('hello:' + msg);
        console.log('data from client: ---> ' + msg);
    });
 
    // 断开处理
    client.on('disconnect', function() {
    
    
        console.log('Client socket has closed.'); 
    });
});

7. Nginx反向代理

Nginx 实现原理类似于 Node 中间件代理,需要你搭建一个中转 nginx 服务器,用于转发请求。

使用 nginx 反向代理实现跨域,是最简单的跨域方式。只需要修改 nginx 的配置即可解决跨域问题,支持所有浏览器,支持 session,不需要修改任何代码,并且不会影响服务器性能。

We only need to configure nginx and configure multiple prefixes on one server to forward http/https requests to multiple real servers. In this way, all urls on this server have the same domain name, protocol and port. Therefore, for browsers, these urls are all of the same origin, and there is no cross-domain restriction. And in reality, those urls are actually served by physical servers. JavaScript inside these servers can call urls on all of these servers across domains.

Download nginx first, and then modify nginx.conf in the nginx directory as follows:

server {
    
    
 
    #nginx监听所有localhost:8080端口收到的请求
	listen       8080;
	server_name  localhost;
 
	# Load configuration files for the default server block.
	include /etc/nginx/default.d/*.conf;
    #localhost:8080 会被转发到这里
	#同时, 后端程序会接收到 "192.168.25.20:8088"这样的请求url
	location / {
		proxy_pass http://192.168.25.20:8088;
	}
	#localhost:8080/api/ 会被转发到这里
    #同时, 后端程序会接收到 "192.168.25.20:9000/api/"这样的请求url
	location /api/ {
		proxy_pass http://192.168.25.20:9000;
	}
	error_page 404 /404.html;
		location = /40x.html {
	}
	error_page 500 502 503 504 /50x.html;
		location = /50x.html {
	}
}

Reference 1: 9 common front-end cross-domain solutions

Reference 2: What is cross domain? Cross domain solution

Guess you like

Origin blog.csdn.net/qq_43000315/article/details/125355180