AJAX

本文详细介绍了Ajax的工作原理和技术细节,包括XMLHttpRequest的使用方法、请求与响应处理、进度事件等。此外,还深入探讨了跨源资源共享(CORS)机制,讲解了不同浏览器下CORS的实现方式以及几种跨域解决方案。
摘要由CSDN通过智能技术生成

Ajax是Asynchronous Javascript and XML的缩写。它不是一门语言,只是一种开发技术,能够在不卸载页面的情况下向服务器请求数据并更新局部的Dom,比起以往Web的“单击、等待”方式用户体验得到了极大的提升。
XMLHttpRequest 是 AJAX 的基础。最初由微软引入的一个新特性。
XMLHttpRequest 用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

1、创建 XMLHttpRequest 对象

所有现代浏览器(IE7+、Firefox、Chrome、Safari 以及 Opera)均内建 XMLHttpRequest 对象。

var xhr = new XMLHttpRequest();

IE5,6需要使用 ActiveX 对象:

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

兼容写法:

var xhr;
ifwindow.XMLHttpRequest) {
    xhr = new XMLHttpRequest();
} else {
    xhr = new ActiveXObject("Microsoft.XMLHTTP");
}

2、如何向服务器发送请求呢?

XMLHttpRequest提供了两个方法,opensend

方法描述
open (method, url, async)规定请求的类型、URL 以及是否异步处理请求。

method:请求的类型;GET 或 POST
url:文件在服务器上的位置
async:true(异步)或 false(同步)
send(string)将请求发送到服务器。

string:仅用于 POST 请求


注:
    url是相对于执行代码的当前页面的相对路径,也可以使用绝对路径。
    调用open并不会真正发送请求,只是启动一个请求以备发送。

GET方式和POST有什么区别?

 
与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。
然而,在以下情况中,请使用 POST 请求:
无法使用缓存文件(更新服务器上的文件或数据库)
向服务器发送大量数据(POST 没有数据量限制)
发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠

例:
Get:

xhr.open("get", "example.php", true);
xhr.open("get", "example.php?t="+Math.random(), ture);//在上面的例子中,可能得到的是缓存的结果。为了避免这种情况,请向 URL 添加一个唯一的 ID。
xhr.open("get", "example.php?name=name1&age=age1", ture);

POST:

xhr.open("post", "example.php", true);


也可以像 HTML 表单那样 POST 数据,请使用 setRequestHeader() 来添加 HTTP 头。然后在 send() 方法中规定您希望发送的数据:

xhr.open("post","example.php",true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send("fname=Bill&lname=Gates");

send()方法,用于发送请求。此方法接受一个参数,即一个座位请求主体发送的数据。如果不需要通过请求主体发送数据,则必须传入null,send(null),因为对于有些浏览器来说是必须的。调send方法后,请求就会被分派到服务器。

还可以使用bort()方法来取消异步请求,调用这个方法后,XHR就会停止触发事件,这时不再允许访问与响应有关的对象属性。

xhr.abort();

注:在终止请求之后,还应该对XHR对象进行解引用操作。由于内存原因,不建议重用XHR对象。

xhr = null;

3.服务器响应数据

服务器的响应信息都存放在xhr的属性中

xhr.responseText;//    字符串形式的响应数据。
xhr.responseXML;//  获得 XML 形式的响应数据。如需其中数据需要对XML进行解析。
xhr.status;//  响应的HTTP状态
xhr.statusText;//  HTTP状态的说明

4.readystatechange事件
此事件每当readyState改变时就会触发,因为要响应改变,所以应该在open()方法调用之前指定处理函数onreadystatechange

AJAX指的是异步XHR请求,也就是async为ture。当数据请求处理完成时,可以使用onreadystatechange事件函数处理。

xhr.onreadystatechange () {
    if (xhr.readyState == 4 && xhr.status ==200 ){
        document.getElementById("box").innerHtml = xhr.responseText;
    }
}
xhr.open("get", "example.php", true);
xhr.send();

但是async为false时不需要指定onreadystatechange事件,只需要要继续执行的代码写在数据请求语句的后面便可。

xhr.open("get", "example.php", false);
xhr.send();
document.getElementById("box").innerHtml = xhr.responseText;


5.XMLHttpRequst 属性

属性描述
onreadystatechangereadystatechange的处理函数,每当 readyState 属性改变时,就会调用该函数。
readyState存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。

0: 请求未初始化。尚未调用open()方法
1: 启动。服务器连接已建立。已调用open()未调用send()
2:发送。 请求已接收。已调用send(),但未收到响应
3: 接收。请求处理中。已经收到部分响应数据
4:完成。 请求已完成,且响应已就绪。数据接受完成,并可以在客户端使用
status响应的HTTP状态

200: “OK”
304: 资源未被修改,可以使用缓存数据
404: 未找到页面
statusTextHTTP状态说明


(xhr.status >= 200 && xhr.status <300) || xhr.status == 304)//表示请求成功

6.HTTP头部信息

每个HTTP请求和响应都会带有相应的头部信息,XHR对象也提供了操作者两种头部信息的方法。

setRequestHeader(); //方法可以设置自定义的请求头部信息,有两个参数,一个是头部字段的名称,另一个是头部字段的值。要成功发送请求头部信息,必须在调用o pen方法之后,调用send方法之前调用此方法。
getResponseHeader(str);//可以获取指定的头部字段名为str的响应头部信息。
getAllResponseHeaders()//可以获取所有的响应头部信息组成的长字符串

7.进度事件

loadstart  在接收到数据的第一个字节时触发 
progress 在接收响应期间持续触发
error 在请求发生错误时触发
abort 在因为调用abort()方法而终止时触发
load 在接收到完整的响应数据时触发
loadend 在通信完成或者触发error、aboart或load事件后触发

但他们在兼容性上有差异。

8.跨源资源共享

   跨源资源共享也叫CORS,是Cross-Origin  Resource Sharing的简称,是为了解决XHR的同源策略的束缚。XHR的同源策略为通信设置了“相同的域,相同的端口,相同的协议”这一限制,试图访问上述限制之外的资源都会引发安全错误。 
CORS的基本思想,就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应食应该成功,还是应该失败。

IE8的实现
通过一个类似于XHR的新对象XDR(XDomainRequest),它部分实现了W3C的CORS规范。XDR与XHR的不同之处在于:

  • cookie不会随请求发送,也不会随响应返回
  • 只能设置请求头部信息中的Content-Type字段
  • 不能访问响应头部信息
  • 只支持GET和POST请求

使用方法:

var xdr = new XDomainRequest();
xdr.onload = function(){//响应触发事件处理程序
    alert(xdr.responseText);//信息还是保存在responseText中
}
xdr.onerror = function(){//失败触发事件处理程序
    alert("An error occurred");
}
xdr.timeout = 1000;//设置超时,超过时间就会触发timeout事件
xdr.ontimeout = funtion(){  //超时处理程序
    alert("Request took too long");
}
xdr.open("get", "http://www.somewhere.com/page/");//无async,因为XDR只能发送异步请求。
xdr.send(nul);

只要响应就会触发load事件,如果失败则触发error事件。

在请求返回前调用xdr.abort()可以终止请求。

为了支持POST请求,XDR对象提供了contentType属性,用来表示发送数据的格式。这个属性是XDR对象影响头部信息的唯一方式。

...
xdr.open("post", "http://www.somewhere.com/page/");
xdr.contentType = "application/x-www-form-urlencoded";
xdr.send("name=value1&age=value2");

其他浏览器对CORS的实现

实现了CORS的这些浏览器,通过XHR对象实现了CORS的原生支持。只需要在请求的open()方法中传入绝对的路径便可。

xhr.open("get", "http://www.somewhere.com/page/", true);
xhr.send(null);

跨域的xhr依然可以访问status和statusText。但它也有所限制:

  • 不能使用setRequestHeader()设置自定义头部。
  • 不能发送和接受cookie
  • 调用getAllRequestHeaders()方法总会返回空字符串

由于同源请求和跨源请求都使用相同的接口,因此建议,本地资源使用相对URL,远程资源使用绝对URL。以示区别。

Preflighted Requests
占位

跨浏览器的CORS
首先检查XHR是否支持CORS,也就是检查withCredentials属性,再检测XDomainRequest是否存在

function createCORSRequest(method,url){
    var xhr = new XMLHttpRequest();
    if("withCredentials" in xhr) {
        xhr.open(method,url,true)
    } else if (window.XDomainRequest) {
        xhr = new XDomainRequest();
        xhr.open(method,url);
    } else {
        xhr = null;
    }
    return xhr;
}
var request = createCORSRequest("get","http://www.somewhere.com/page/");
if (request) {
    request.onload = function(){
        alert(request.responseText);
    };
    request.send(null);
}

其他跨域技术

1、图像Ping。原理:网页可以从任何网页中加载图像,不用担心是否跨域。

var img = new Image();
img.onload = img.error = function(){
    //doSomething
};
img.src = "http://www.somewhere.com/page/test?name=value1";

图像Ping,浏览器得不到任何具体的数据,只能通过时间监听其响应状态。并且,它只能发送GET请求,因此只能用于浏览器与服务器的单向通信。

2、JSONP
JSONP是JSON with padding(填充式JSON或参数式JSON)的简写。
JSONP由两部分组成:对调函数和数据。对调函数是响应到来时应该在页面中调用的函数,回调函数的名字一般是在请求中指定的,而数据就是传入回调函数的JSON数据。

callback({"name": "张三"});//JSONP格式
http://freegeoip.net/json/?callback=handleResponse ; //典型的JSONP请求,handleResponse是回调函数名

JSONP是通过动态<script>元素来使用的,使用时可以为src属性指定一个跨域URL。JSONP是有效的javascript代码,所以在请求完成后,即在JSONP响应加载到页面中以后,就会立即执行。

function handleResponse () {
    //doSomething
}
var script = document.creatElement("script");
script.src = "http://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script,document.body.firstChild);

JSONP可以直接访问响应文本,且支持双向通信。

JSONP的不足在于,安全以及确定是否失败。

3、Comet
ajax是页面向服务器请求数据,Comet是服务器向页面推送数据。
实现Comet的方式有两种:长轮询

既然有长轮询,就一定有短轮询,短轮询也称传统轮询。短轮询是浏览器间隔一定时间就向服务器发送请求,服务器立即响应。
这里写图片描述

长轮询:页面发起一个请求到服务器,服务器一直保持连接打开,直到有数据可以发送。发送完数据之后,浏览器关闭连接,随即又发送一个新请求到服务器。
这里写图片描述

长轮询和短轮询,浏览器都要在接收数据之前先发起对服务器的连接,两者的最大区别在于,服务器如何响应并发送数据。

流:流在整个生命周期内只使用一个HTTP连接。浏览器只像服务器发送一份请求,服务器保持连接打开,然后周期性的向浏览器发送数据。
这里写图片描述

在非IE浏览器中通过侦听readystatechange事件及检测readyState的值是否为3就可以利用XHR实现HTTP流。因为每次结果都会缓存在XHR的responseText中,因此需要比较之前接受到的数据,处理后才能拿到最新的数据。

4、SSE
SSE(Server-Sent Events)服务器发送事件,它是围绕只读Comet交互推出的API或者模式。SSE API用于创建页面到服务器的单向连接,服务器通过这个连接可以发送任意数量的数据。服务器响应的MIME类型必须是text/evnet-stream,而且是浏览器中的javascript API能解析格式输出。SEE支持长轮询,短轮询和HTTP流,而且在断开连接时自动确定何时重新连接。

var source = new EventSource("example.php");

传入的URL必须同源,EventSource实例有一个readyState属性,0 表示正在连接到服务器,1表示打开了连接,2表示关闭了连接。同时还有三个事件:

  • open 在建立连接时触发
  • message 从服务器接收到新事件时触发
  • error 在无法建立连接时触发

message处理函数有一个参数event对象,服务器返回的数据保存在event.data中。
默认情况下,EventSource对象会保持与服务器的活动连接。如果断开连接,还会重新连接。这表明SSE更适合长轮询和HTTP流。如果想要强制断开连接不再重连,可以使用close()方法

source.close();

5.Web Sockets
目标是在一个单独的持久连接上提供全双工、双向通信。在Javascript建立了Web Socket之后,会有一个HTTP请求发送到浏览器以发起连接。在取得服务器响应后,建立的连接会使用HTTP升级从HTTP协议交换为Web Socket协议。标准的HTTP服务器无法实现Web Sockets,只有支持这种协议的服务器才能正常工作。
URL格式使用ws://,加密的连接wss://
Web Sockets API

var socket = new WebSocket("ws://www.example.com/server.php");//URL必须是绝对路径,因此可以通过它打开到任何站点的连接

WebSocket也有readyState属性:

  • WebSocket.OPENING (0):正在建立连接
  • WebSocket.OPEN (1):已经建立链接
  • WebSocket.CLOSING (2):正在关闭连接
  • WebSocket.CLOSE (3):已经关闭连接

要关闭Web Socket连接,可以在任何时候调用close()方法

socket.close();//调用之后readyState值立即变为2,关闭后则变为3.

建立连接后就可以接收和发送数据了。要向服务器发送数据,使用send()方法,并传入任意字符串

socket.send("Hello world");

Web Sockets只能通过连接发送纯文本,所以复杂数据必须序列化。
当服务器向客户端发来消息时,WebSocket对象就会触发message事件,返回的数据仍在evnet.data中。WebSocket对象还有其他三个事件,在连接生命周期的不同阶段触发

  • open 在成功建立连接时触发
  • error 在发生错误时触发,连接不能持续。
  • close 在连接关闭时触发

WebSocket对象不支持DOM 2级事件侦听器,因此必须使用DOM 0级语法分别定义每个事件处理程序。

socket.open = function () {}

其中close 事件的event对象含有额外的信息,有三个额外属性:wasClean、code、reason。其中wasClean是一个布尔值,表示连接是否已经明确的关闭;code是服务器返回的数值状态码;而reason包含服务器发回的消息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值