前端基础复习-AJAX,XHR,跨域

Ajax

Ajax 翻译成中文叫做异步 JavaScript+xml。这种技术可以实现向服务器请求额外的数据而不重新加载也页面

实现 Ajax:XMLHttpReqest

XMLHttpRequest 是 AJAX 的基础。所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject)。

XMLHttpRequest 用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

创建

1
var XHR = new XMLHttpReqest();

使用方法

使用 XHR 时,第一个方法是 open()它启动一个请求以备发送,接收三个参数

  • 请求类型(get/post)
  • 请求的 url(相对于执行代码的当前页面)
  • Boolean true 表示异步,false 表示同步

发送请求:send(),接受一个参数,为请求主体发送的数据,如果不发送则必须填 null。

属性

接受响应后,响应的数据自动填充 XHR 对象的属性:

  • responseText: 响应主体返回的文本
  • responseXML: 如果响应内容类型是‘text/xml’,或“application/xml”时,XML DOM 保存再这个属性中。
  • status:响应的 http 状态
  • statusText:http 状态说明
  • readyState: 表示请求/响应过程中当前的活跃阶段,有以下取值
    • 0:未初始化,尚未调用 open()
    • 1: 启动,未调用 send()
    • 2: 发送,调用 send(),未接收响应
    • 3:接受,已经接收到部分响应数据。
    • 4:完成,接收到所有数据

HTTP 头部信息

XML 可以通过 setResquestHeader()来定义 http 响应的头部。默认下发送 XMR 请求同时还会发送下列头部信息。

  • Accept:浏览器能处理的内容类型。
  • Accept-Charset: 浏览器能够显示的字符集
  • Accept-encoding:浏览器能够处理的压缩编码
  • Accept-language:浏览器当前设置的语言
  • Connection: 浏览器与服务器之间
  • Cookie:当前页面设置的任何 Cookie。
  • Host: 发出请求页面所在域
  • Referer: 发出请求页面的 url

一个完整实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (window.XMLHttpReqest) {
var XHR = new XMLHttpReqest();
// code for IE7+, Firefox, Chrome, Opera, Safari
} else {
// code for IE6, IE5
var XHR = new ActiveXObject("Microsoft.XMLHTTP");
}
XHR.open('post','server.php',true);
XHR.send();
XHR.onreadyStatechange = function () {
if (XHR.readyState ==4) {
if (XHR.status >= 200 && XHR.status < 300 || XHR.status == 304) {
var data = JSON.parse(request.responseText);
} else {
alert("发生错误:" + request.status);
}
}
}

jQuery:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$.ajax({
type: "GET",
url: "http://localhost/AJAX/server.php?number=" + $("#keywords").val(),
dataType: "json",
success: function(data) {
if (data.success) {
// $("#result").html(data.msg);
} else {
// $("#result").html("出现错误:" + data.msg);
}
},
error: function(jqXHR){
alert("发生错误:" + jqXHR.status);
},
})

XMLHttpReqest2 级

FormData 类型

formData 可以序列化的表单,创建与表单类似的数据

1
2
3
4
5
var data = new FormData()
data.append('name', 'value');

var form = new FormData(document.forms[0])
xhr.send(form)

超时设定 in

xhr timeout 属性,表示等待响应多少毫秒后终止。

1
2
3
4
xhr.timeout = 1000//超时设置为1s
xhr.ontimeout = function() {
//
}

progress 事件

progress 事件再浏览器接受新数据期间周期性触发。onprogress 收到一个 event 对象,其 target 属性时 xhr 对象,其 target 属性时 xhr 对象,包含额外三个属性:

  • lengthComputable: 表示进度信息是否可用的布尔值
  • position: 已经接收的字节数
  • totalSize: 根据 content-length 响应头部确定的预期字节数
1
2
3
4
5
6
7
8
xhr.onprogress = function() {
var divStatus = document.getElementByID("status");
if (event.lengthComputable) {
divStatus.innerHTML = "recived" + event.position + "of" + event.totalSize + "btyes"
} else {
//error
}
}

onprogress 必须在 open()

跨域

浏览器为了安全,实施了同源策略,即协议,域名,端口相同。不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。想要突破同源策略的限制,必须采用跨域的技术

CORS

CORS(Cross-Origin Resource Sharing,跨域资源共享)定义了在跨域访问资源时,浏览器和服务器之间如何沟通。其背后的思想就是使用自定会议的 HTTP 头部让浏览器和服务器进行沟通

例如一个简单的 get/post 请求,为其添加一个自定义的头部 Origin,其中包含请求页面的信息。

Origin: http://www.xxx.com

如果服务器认为这个请求可以接收,则在 Access-Control-Allow-Origin 头部中回发相同源的信息

Access-Control-Allow-Origin: http://wwww.xxx.com

或者在服务端中加入

header( “Access-Control-Allow-Origin:*“ );

header( “Access-Control-Allow-Methods:POST,GET” );

图像 ping

利用标签来实现跨域,由于网页能从任何网页中加载图像,因此不用担心跨域,使用 img 的.src
属性,在其中写要请求的地址来实现跨域

1
2
3
4
5
var img = new Image();
img.onload = img.onerror = function() {
alert('done!');
};
img.src = "http://www.xxx.com"

缺点:只能发送 get 请求,无法访问响应文本

JSONP

JSONP = Json with padding.由两部分组成,回掉函数和数据。回调函数是当响应到来时在页面中调用的
函数,其名字在请求中指定。数据就是传入回调函数中 json 的数据。jsonp 使用动态 script 实现跨域,用 src
属性指定跨域 URL。

jsonp 通过动态 script 元素来使用,因为 srcipt 标签的 src 属性不受同源策略限制

一个典型的 jsonp 请求

http://freegeoip.net/json/?callback=handleResponse

1
2
3
4
5
6
function handleResponse() {
alert("xxx"+ response.ip+response.city)
}
var script = document.creatElement("script");
script.src = "http://xxx"
document.body.insertBefore(script, document.body.firstchild)

window.name+iframe

​ window.name 通过在 iframe(一般动态创建 i)中加载跨域 HTML 文件来起作用。然后,HTML 文件将传递给请求者的字符串内容赋值给 window.name。然后,请求者可以检索 window.name 值作为响应。

iframe 标签的跨域能力;
window.name 属性值在文档刷新后依旧存在的能力(且最大允许 2M 左右)。
每个 iframe 都有包裹它的 window,而这个 window 是 top window 的子窗口。contentWindow 属性返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
 //下述用端口
//10000表示:domainA
// 10001表示:domainB


<!-- localhost:10000 -->
<script>
var iframe = document.createElement('iframe');
iframe.style.display = 'none'; // 隐藏

var state = 0; // 防止页面无限刷新
iframe.onload = function() {
if(state === 1) {
console.log(JSON.parse(iframe.contentWindow.name));
// 清除创建的iframe
iframe.contentWindow.document.write('');
iframe.contentWindow.close();
document.body.removeChild(iframe);
} else if(state === 0) {
state = 1;
// 加载完成,指向当前域,防止错误(proxy.html为空白页面)
// Blocked a frame with origin "http://localhost:10000" from accessing a cross-origin frame.
iframe.contentWindow.location = 'http://localhost:10000/proxy.html';
}
};

iframe.src = 'http://localhost:10001';
document.body.appendChild(iframe);
</script>

<!-- localhost:10001 -->
<!DOCTYPE html>
...
<script>
window.name = JSON.stringify({a: 1, b: 2});
</script>
</html>

注意:

直接嵌入其他域(localhots:10001)下的 URL 会报错,所以需要加载完成替换为当前域的 URL(localhots:10000),proxy.html 为空白页面,只为解决该问题;
跨域请求 iframe
重新设置 src(http://localhost:10000/proxy.html)后导致页面不断刷新,所以通过state来控制;
全部获取完结果后,清除该 iframe。

websocket

WebSocket protocol 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是 server push 技术的一种很棒的实现。WebSocket