您的位置:首页 > Web前端 > JavaScript

js--ajax和跨域

2016-05-01 16:25 525 查看

1.Ajax 是什么? 如何创建一个Ajax?请尽可能详尽的解释 Ajax 的工作原理?使用 Ajax 都有哪些优劣?

ajax是什么

1.AJAX = 异步 JavaScript 和 XML。

2.AJAX 是一种用于创建快速动态网页的技术。

3.通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

XMLHttpRequset对象

ajax的核心是XMLHttpRequest对象(IE5和IE6使用ActiveXObject)

XMLHttpRequest 对象用于和服务器交换数据。使用XMLHttpRequest可以

1.不重新加载页面情况下更新网页

2.页面加载从服务器请求数据和接收数据

3.在后台向服务器发送数据

var xhr;

if(window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}


ajax向服务器发送请求

如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open() 和 send() 方法

open(method,url,async);-启动请求,以备发送。规定请求的类型,url以及是否异步处理请求。

method:请求的类型;GET 或 POST

url:文件在服务器的位置

asycn:true是异步,false是同步

send(string);–将请求发送到服务器。

string:仅用于post请求

服务器响应

收到服务器响应后,响应数据会自动填充XHR对象的以下属性。

responseText:获得字符串形式的响应数据

responseXML:获得 XML 形式的响应数据

status:响应的HTTP状态

statusText:HTTP状态的说明

收到响应后,第一个检查的是status属性,以确定响应已经成功返回。一般可以让状态码200作为成功的标记,这时respomseText和responseXML都可以访问了。但若状态码是304表示资源未被修改,可以直接使用浏览器的缓存版本。这样都是响应成功的意思。代码如下:

if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
alert(xhr.responseText);
} else {
//在IE浏览器中创建XMLHttpRequest对象
alert("Request was unsuccessful:" + xhr.status);
}


status:

200: “OK”

403 (禁止) 服务器拒绝请求。

404 (未找到) 服务器找不到请求的网页。

408 (请求超时) 服务器等候请求时发生超时。

500 (服务器内部错误) 服务器遇到错误,无法完成请求。

HTTP状态码分为五类:

1xx–请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束。

2xx–代表请求已成功被服务器接收、理解、并接受。

–200 :服务器已成功处理了请求并提供了请求的网页。

–204: 服务器成功处理了请求,但没有返回任何内容。

3xx–重定向,这类状态码代表需要客户端采取进一步的操作才能完成请求。

–301: 请求的网页已永久移动到新位置。当URLs发生变化时,使用301代码。搜索引擎索引中保存新的URL。

–302: 请求的网页临时移动到新位置。搜索引擎索引中保存原来的URL。

–304: 如果网页自请求者上次请求后没有更新,则用304代码告诉搜索引擎机器人,可节省带宽和开销。

4xx–客户端错误,客户端看起来可能发生了错误,妨碍了服务器的处理。

–400: 服务器不理解请求的语法

–403: 服务器拒绝请求。

–404: 服务器找不到请求的网页。服务器上不存在的网页经常会返回此代码。

–410 :请求的资源永久删除后,服务器返回此响应。该代码与 404(未找到)代码相似,但在资源以前存在而现在不存在的情况下,有时用来替代404 页面代码。如果资源已永久删除,应当使用 301 指定资源的新位置。

5xx–服务器错误,服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。

–500 :服务器遇到错误,无法完成请求。

–503: 服务器目前无法使用(由于超载或停机维护)。

onreadystatechange事件

我们一般都是发送异步请求,才能让js继续执行不必等待响应。此时,可以检测XHR对象的readyState属性,此属性表示当前请求/响应所处的阶段。

readyState:

属性存有 XMLHttpRequest 的状态信息:

0: 请求未初始化。尚未调用open方法

1: 启动。已经调用open方法,但没调用send方法

2: 发送。已经调用send方法,但尚未接收到响应。

3: 接收。已经接收到部分响应数据。

4: 完成。已经接收到全部响应数据,而且已经可以在客户端使用了。

每当readyState状态改变的时候,会触发onreadystatechange事件,可利用此事件来检测每次状态变化后readystate的值。

在 onreadystateChange 事件中,我们规定当服务器响应已做好被处理的准备时所执行的任务。

当 readyState 等于 4表示所有数据已经就绪。

xhr.onreadystateChange = function() {
if(xhr.readyState == 4) {
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
alert(xhr.responseText);
} else {
alert("Request was unsuccessful:" + xhr.status);
}
}
}


ajax异步请求的步骤:

(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象

(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息open

(3)设置响应HTTP请求状态变化的函数,设置回调函数

(4)发送HTTP请求send

(5)获取异步调用返回的数据,接收响应数据,判断对象的状态是否完成交互

(6)若完成,则使用JavaScript和DOM实现局部刷新

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
function loadXMLDoc()
{
var xhr;
if (window.XMLHttpRequest)
{
//  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
xhr=new XMLHttpRequest();
}
else
{
// IE6, IE5 浏览器执行代码
xhr=new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.onreadystatechange=function()
{
if(xhr.readyState == 4) {
if((xhr.state >= 200 && xhr.state < 300) || xhr.state == 304) {
document.getElementById("myDiv").innerHTML=xhr.responseText;
}
}
}
xhr.open("GET","/try/ajax/ajax_info.txt",true);
xhr.send();
}
</script>
</head>
<body>

<div id="myDiv"><h2>使用 AJAX 修改该文本内容</h2></div>
<button type="button" onclick="loadXMLDoc()">修改内容</button>

</body>
</html>


ajax的优缺点

优点:

1.无刷新更新数据,优秀的用户体验

2.ajax不需要任何插件支持,可以被大多数主流浏览器支持

3.减少服务器和带宽的负担。在客户端创建ajax引擎,把传统方式下的服务器负担的工作转移到客户端,便于客户端资源来处理,减轻服务器和带宽的负担。

缺点:

1.浏览器对XMLHttpRequest对象支持度不足。ajax大量的使用了javascript和ajax引擎,这些取决于浏览器的支持.在编写的时候考虑对浏览器的兼容性.

2.破坏浏览器前进和后退按钮。ajax只是局部刷新,所以页面的后退按钮是没有用的.

3.开发和调试工具的缺乏。js是ajax的主要组成部分,但是缺少很好的js开发和调试工具。

2.jQuery的ajax

jQuery的ajax进行了封装

1.最底层的ajax实现是:.ajax()2.第二层是load(),.get(),.post()3.第三层是.getScript(),$.getJSON()

$.ajax()

url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址。

type:请求方式(post或get)默认为get。

data:发送到服务器的数据。如果已经不是字符串,将自动转换为字符串格式。对象必须为key/value格式,例如{foo1:”bar1”,foo2:”bar2”}转换为&foo1=bar1&foo2=bar2。

datatype:预期服务器返回的数据类型。(xml,html,script,json,jsonp,text)

xml:返回XML文档,可用JQuery处理。

html:返回纯文本HTML信息;包含的script标签会在插入DOM时执行。

script:返回纯文本JavaScript代码。不会自动缓存结果。除非设置了cache参数。注意在远程请求时(不在同一个域下),所有post请求都将转为get请求。

json:返回JSON数据。

jsonp:JSONP格式。使用SONP形式调用函数时,例如myurl?callback=?,JQuery将自动替换后一个“?”为正确的函数名,以执行回调函数。

text:返回纯文本字符串。

success:要求为Function类型的参数,请求成功后调用的回调函数,有两个参数。

(1)由服务器返回,并根据dataType参数进行处理后的数据。

(2)描述状态的字符串。

$(function(){
$('#send').click(function(){
$.ajax({
type: "GET",
url: "test.json",
data: {username:$("#username").val(), content:$("#content").val()},
dataType: "json",
success: function(data){
$('#resText').empty();   //清空resText里面的所有内容
var html = '';
$.each(data, function(commentIndex, comment){
html += '<div class="comment"><h6>' + comment['username']
+ ':</h6><p class="para"' + comment['content']
+ '</p></div>';
});
$('#resText').html(html);
}
});
});
});


load()

load()-常用来在服务器上获取静态的数据文件

.get()和.post()

.get(url[.data][.callback][.type]).post(url [.data] [.callback] [.type])

1.服务器端返回的数据格式是HTML片段

$("#send").click(function(){
$.get("get1.php",{
username:$("#username").val(),
content:$("#content").val()
},function(data,textStatus){
$("#resText").html(data);
});
});


2.服务器端返回的数据格式是XML片段

$("#send").click(function(){
$.get("get2.php",{
username: $("#username").val();
content: $("#content").val();
},function(data,textStatus){
var username = $(data).find("comment").attr("username");
var content = $(data).find("comment content").text();
var txtHtml = "<div class="comment"><h6>"+username+"</h6><p class="para">"+content+"</p></div>";
$("#resText").html(txtHtml);
});
});


3.返回的数据格式是json片段

$("#send").click(function(){
$.get("get3.php",{
username: $("#username").val();
content: $("#content").val();
},function(data,textStatus){
var username = data.username;
var content = data.content;
var txtHtml = "<div class="comment"><h6>"+username+"</h6><p class="para">"
+content+"</p></div>";
$("#resText").html(txtHtml);
},"json");
});


3.什么是跨域资源共享 (CORS)?它用于解决什么问题?

CORS它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

CORS就是使用自定义的http头部让浏览器和服务器进行沟通。从而决定请求或响应是应该成功还是失败。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

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

平时的ajax请求可能是这样的:

<script type="text/javascript">
var xhr = new XMLHttpRequest();
xhr.open("POST", "/damonare",true);
xhr.send();
</script>


以上damonare部分是相对路径,如果我们要使用CORS,相关Ajax代码可能如下所示:

<script type="text/javascript">
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://segmentfault.com/u/trigkit4/",true);
xhr.send();
</script>


jquery的CORS实现方式

以 服务器 3000 上的请求页面向 服务器 3001 发送请求为例。

服务器 3000 上的请求页面 JavaScript 不变,如下:

$(function() {
$("#submit").click(function() {
var data = {
name: $("#name").val(),
id: $("#id").val()
};
$.ajax({
type: 'POST',
data: data,
url: 'http://localhost:3001/cors',
dataType: 'json',
cache: false,
timeout: 5000,
success: function(data) {
console.log(data)
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('error ' + textStatus + ' ' + errorThrown);
}
});
});
});


CORS域jsonp的对比

1.CORS 除了 GET 方法外,也支持其它的 HTTP 请求方法如 POST、 PUT 等。

2.CORS 可以使用 XmlHttpRequest 进行传输,所以它的错误处理方式比 JSONP 好。

3.JSONP 可以在不支持 CORS 的老旧浏览器上运作。

4.JSONP-json with padding(回调函数和数据组成.)

jsonp原理

原理:

Ajax直接请求普通文件存在跨域无权限访问的问题,但是调用js文件时则不受是否跨域的影响。

所以jsonp就是通过动态创建

function handleResponse(response){
alert("ip address" + response.ip + "which is in" + response.city + "," + response.region_name);
}
var script = document.createElement("script");
//有个a.html页面,它里面的代码需要利用ajax获取一个不同域上的json数据,假设这个json数据地址是http://example.com/data.php,
script.src = "http://example.com/data.php?callback=handleResponse";
document.body.insertBefore(script,document.body.firstChild);


服务器解析之后,传递给handleResponse函数的是一个json,如下所示:

handleResponse({
"ip":123,
"city":"beijing",
"region_name":"ss"
});


jquery的jsonp:

$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。

$.getJSON("http://example.com/data.php?callback=handleResponse",function(response){
//处理获得的json数据
});


使用 jQuery 集成的 $.ajax 实现 JSONP 跨域调用:

// 回调函数
function jsonpCallback(data) {
console.log("jsonpCallback: " + data.name)
}
$("#submit").click(function() {
var data = {
name: $("#name").val(),
id: $("#id").val()
};
$.ajax({
url: 'http://localhost:3001/ajax/deal',
data: data,
dataType: 'jsonp',
cache: false,
timeout: 5000,
// jsonp 字段含义为服务器通过什么字段获取回调函数的名称
jsonp: 'callback',
// 声明本地回调函数的名称,jquery 默认随机生成一个函数名称
jsonpCallback: 'jsonpCallback',
success: function(data) {
console.log("ajax success callback: " + data.name)
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(textStatus + ' ' + errorThrown);
}
});
});


jsonp优缺点

优点:

1.简单易用

2.可以直接访问响应文本,支持浏览器和服务器的双向通信。

缺点:

1.从其他域加载代码,不能判断其他域是否安全。

2.利用 JSONP 格式返回的值一段要立即执行的 JavaScript 代码,所以不会像 ajax 的 XmlHttpRequest 那样可以监听不同事件对数据进行不同处理。与 Ajax 对比,由于不是通过 XmlHttpRequest 进行传输,所以不能注册 success、 error 等事件监听函数。

3.只能使用 GET 方法发起请求,这是由于 script 标签自身的限制决定的。

jsonp不是ajax

1.ajax和jsonp都是请求一个url,然后把服务器返回的数据进行处理

2.但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加

5.document.domain来跨子域

document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同

比如http://www.example.com/a.htmlhttp://example.com/b.html 设置成document.domain = ‘example.com’;

//a.html
<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>
<script type="text/javascript">
document.domain = 'example.com';//设置成主域
function test(){
alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象
}
</script>

//b.html
<script type="text/javascript">
document.domain = 'example.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同
</script>


6.window.name跨域

即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。

a.html获取data.html的数据过程:

1.在data.html給当前的window.name设置一个a.html页面想要得到的数据值。

2.a.html页面中使用一个隐藏的iframe来充当一个中间人角色,由iframe去获取data.html的数据,然后a.html再去得到iframe获取到的数据。

3.iframe想要获取到data.html的通过window.name设置的数据,只需要把这个iframe的src设为www.cnblogs.com/data.html就行了。

4.a.html想要得到iframe所获取到的数据,也就是想要得到iframe的window.name的值,还必须把这个iframe的src设成跟a.html页面同一个域才行

//data.html
<script>
window.name="我是a.html想要的内容";
</script>

//a.html
<script>
//iframe载入data.html页面后会执行函数
function getData(){
var iframe = document.getElementById("proxy");
iframe.onload = function(){
//这时a.html和iframe已经是同一个源了,可以互相访问
var data = iframe.contentWindow.name;//成功获取到了数据
};
//只是随便写的一个页面,只要和a.html同源就可以,设置成about:blank也可以
iframe.src = 'b.html';
}
</script>
<iframe id="proxy" src="http://www.cnblogs.com/data.html" style="display:none" onload=getData()></iframe>


这种方法与 document.domain 方法相比,放宽了域名后缀要相同的限制,可以从任意页面获取 string 类型的数据。

7.通过HTML5的postMessage方法跨域–比较直观和方便的,但是缺点是IE6、IE7不支持,所以用不用还得根据实际需要来决定。

window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

这个功能主要包括接受信息的”message”事件和发送消息的”postMessage”方法。比如damonare.cn域的A页面通过iframe嵌入了一个google.com域的B页面,可以通过以下方法实现A和B的通信

A页面通过postMessage方法发送消息:

window.onload = function() {
var ifr = document.getElementById('ifr');
var targetOrigin = "http://www.google.com";
ifr.contentWindow.postMessage('hello world!', targetOrigin);
};


postMessage的使用方法:

otherWindow.postMessage(message, targetOrigin);

otherWindow:指目标窗口,也就是给哪个window发消息,是 window.frames 属性的成员或者由 window.open 方法创建的窗口

message: 是要发送的消息,类型为 String、Object (IE8、9 不支持)

targetOrigin: 是限定消息接收范围,不限制请使用 ‘*

B页面通过message事件监听并接受消息:

var onmessage = function (event) {
var data = event.data;//消息
var origin = event.origin;//消息来源地址
var source = event.source;//源Window对象
if(origin=="http://www.baidu.com"){
console.log(data);//hello world!
}
};
if (typeof window.addEventListener != 'undefined') {
window.addEventListener('message', onmessage, false);
} else if (typeof window.attachEvent != 'undefined') {
//for ie
window.attachEvent('onmessage', onmessage);
}


同理,也可以B页面发送消息,然后A页面监听并接受消息。

8.ajax处理跨域有几种方式?

不同域
http:// www . google : 8080 / script/jquery.js
http:// (协议号protocal) www (子域名domain)google (主域名)8080 (端口号)

只要协议、域名 、端口有任何一个不同, 都被当作是 不同 的域。

跨域的方法

1、通过jsonp跨域

2、通过修改document.domain来跨子域

3、使用window.name来进行跨域

4、使用HTML5中新引进的window.postMessage方法来跨域传送数据(ie 67 不支持)

5、CORS 需要服务器设置header :Access-Control-Allow-Origin。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: