Ajax

1 什么是Ajax?

Web 诞生一开始沿用的是“单击,等待”的交互模式。随着技术的发展,这种技术存在很大的弊端,为了更方便页面与服务器通信,出现了Ajax技术。

Ajax 技术的核心是 XMLHttpRequest 对象(简称 XHR)。

XHR 为向服务器发送请求和解析服务器响应提供了流畅的接口。能够以异步方式从服务器取得信息,意味着用户单击后,可以不必刷新页面也能取得新数据。

Ajax,是对 Asynchronous JavaScript + XML 的简写,虽然名字中包含 XML 的成分,但 Ajax 通信与数据格式无关;不一定是 XML 数据。

2 IE7 及更高版本中,如何创建XHR对象?

var xhr = new XMLHttpRequest();

3 如何发送请求?

xhr.open("get", "example.txt", false);
xhr.send(null);

open方法接受 3 个参数:要发送的请求的类型("get"、 "post"等) 、请求的 URL 和表示是否异步发送请求的布尔值。

有关这行代码,需要说明两点:一是 URL相对于执行代码的当前页面(当然也可以使用绝对路径);二是调用 open()方法并不会真正发送请求,而只是启动一个请求以备发送。

由于这次请求是同步的(false), JavaScript 代码会等到服务器响应之后再继续执行。在收到响应后,响应的数据会自动填充 XHR 对象的属性。

在接收到响应后,第一步是检查 status 属性,以确定响应已经成功返回。

下面是一个完整的例子:

var xhr = new XMLHttpRequest();
xhr.open("get", "example.txt", false);
xhr.send(null);
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
    alert(xhr.responseText);
} else {
    alert("Request was unsuccessful: " + xhr.status);
}

4 http状态码304表示什么意思?

状态代码为 304 表示请求的资源并没有被修改,可以直接使用浏览器中缓存的版本;当然,也意味着响应是有效的。

5 XHR 对象的 readyState 属性有多少值? readystatechange 事件是指什么?

多数情况下,我们是要发送异步请求,才能让JavaScript 继续执行而不必等待响应。

此时,可以检测 XHR 对象的 readyState 属性,该属性表示请求/响应过程的当前活动阶段。

这个属性可取的值如下:

0:未初始化。尚未调用 open()方法。
1:启动。已经调用 open()方法,但尚未调用 send()方法。
2:发送。已经调用 send()方法,但尚未接收到响应。
3:接收。已经接收到部分响应数据。
4:完成。已经接收到全部响应数据,而且已经可以在客户端使用了。

只要 readyState 属性的值由一个值变成另一个值,都会触发一次 readystatechange 事件。可以利用这个事件来检测每次状态变化后 readyState 的值。

通常,我们只对 readyState 值为 4 的阶段感兴趣,因为这时所有数据都已经就绪。

不过,必须在调用 open()之前指定 onreadystatechange事件处理程序才能确保跨浏览器兼容性。

var xhr = new XMLHttpRequest();
//必须open()之前指定 onreadystatechange事件处理程序
xhr.onreadystatechange = function () {
    console.log(xhr.readyState + ":" + xhr.responseText);
}
xhr.open("get", "example.txt", true);
xhr.send(null);

 

6 在接收到响应之前如何取消异步请求?

xhr.abort();

调用这个方法后, XHR 对象会停止触发事件,而且也不再允许访问任何与响应有关的对象属性。

7 如何自定义请求头部信息?

xhr.open("get", "example.php", true);
xhr.setRequestHeader("MyHeader", "MyValue");
xhr.send(null);

8 如何获得响应头部?

var myHeader = xhr.getResponseHeader("MyHeader");

9 使用get方法时,xhr对象的open方法需要注意什么?

open方法的第二个参数中,URL 末尾的查询字符串必须经过正确的编码。如下面的例子所示:

xhr.open("get", "example.php?name1=value1&name2=value2", true);

下面这个函数可以辅助向现有 URL 的末尾添加查询字符串参数:

function addURLParam(url, name, value) {
    url += (url.indexOf("?") == -1 ? "?" : "&");
    url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
    return url;
}

10 post请求

无刷新怎么提交FORM表单的数据到服务器?

11 get请求和post请求的区别

1 安全性:涉及安全性的信息,如用户密码,应采用 post 方式。

2 性能:POST 请求消耗的资源会更多,同样的数据GET 请求的速度最多可达到 POST 请求的两倍。

3 数据量:get大概1-2k,post大很多,80-100k应该是可以的。

4 用途:GET常用于向服务器查询某些信息。POST通常用于向服务器发送应该被保存的数据。

12 XMLHttpRequest 1级中进行表单数据的提交和XMLHttpRequest 2级比较,有什么不同?

两种方法效果都一样,只是用XMLHttpRequest 2级的FormData更方便些。

使用 FormData 的方便之处体现在不必明确地在 XHR 对象上设置请求头部。和进行相应的序列号表单数据。

XMLHttpRequest 1级代码:

var xhr = new XMLHttpRequest();
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);
        }
    }
};

xhr.open("post", "postexample.php", true);
//首先将 Content-Type 头部信息设置为 application/x-www-form-urlencoded
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var form = document.getElementById("user-info");
//以适当的格式创建一个字符串,使用第 14 章介绍的 serialize()函数来创建这个字符串
xhr.send(serialize(form));

XMLHttpRequest 2级代码:

var xhr = new XMLHttpRequest();
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);
        }
    }
};

xhr.open("post", "postexample.php", true);
var form = document.getElementById("user-info");
//FormData 为序列化表单以及创建与表单格式相同的数据(用于通过 XHR 传输)提供了便利。
xhr.send(new FormData(form));

14 load事件和readystatechange事件有什么不同?

readystatechange事件:只要 readyState 属性的值由一个值变成另一个值,都会触发一次 readystatechange 事件。

load事件:在接收到完整的响应数据时触发,相当于xhr对象的readyState 值为 4 的阶段。

readystatechange事件代码如下:

var xhr = new XMLHttpRequest();
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);
        }
    }
};

xhr.open("get", "altevents.php", true);
xhr.send(null);

load事件代码如下:

var xhr = new XMLHttpRequest();
xhr.onload = function(){
    if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
        alert(xhr.responseText);
    } else {
        alert("Request was unsuccessful: " + xhr.status);
    }
};

xhr.open("get", "altevents.php", true);
xhr.send(null);

15 同源策略

通过 XHR 实现 Ajax 通信的一个主要限制,来源于跨域安全策略。默认情况下, XHR 对象只能访问与包含它的页面位于同一个域中的资源。

这种安全策略可以预防某些恶意行为。但是,实现合理的跨域请求对开发某些浏览器应用程序也是至关重要的。

同源策略是对 XHR 的一个主要约束,它为通信设置了“相同的域、相同的端口、相同的协议”这一限制。

试图访问上述限制之外的资源,都会引发安全错误,除非采用被认可的跨域解决方案。

这个解决方案叫做 CORS(Cross-Origin Resource Sharing,跨源资源共享)。

 

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

16 跨源资源共享

CORS 背后的基本思想,就是使用自定义的 HTTP 头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。

服务器根据这个头部信息来决定是否给予响应。

如果服务器认为这个请求可以接受,就在 Access-Control-Allow-Origin 头部中回发相同的源信息(如果是公共资源,可以回发"*")。

例如:Access-Control-Allow-Origin: http://www.nczonline.net,如果没有这个头部,或者有这个头部但源信息不匹配,浏览器就会驳回请求。

17 常用跨域方法

以前要实现跨域访问,可以通过JSONP、Flash或者服务器中转的方式来实现,但是现在我们有了CORS

        CORS与JSONP相比,无疑更为先进、方便和可靠。

        1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。

        2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。

        3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS(这部分会在后文浏览器支持部分介绍)。

现在的方案:CORS

a 微软在 IE8 中引入了 XDR(XDomainRequest)类型。

这个对象与 XHR 类似,但能实现安全可靠的跨域通信。 XDR 对象的安全机制部分实现了 W3C 的 CORS 规范

b Firefox 3.5+、 Safari 4+、 Chrome、 iOS 版 Safari 和 Android 平台中的 WebKit 都通过 XMLHttpRequest对象实现了对 CORS 的原生支持。

要请求位于另一个域中的资源,使用标准的 XHR 对象并在 open()方法中传入绝对 URL 即可。

c 跨浏览器的跨域:

function createCORSRequest(method, url){
    var xhr = new XMLHttpRequest();
    // 检查支持CORS的情况
    // 检查XMLHttpRequest对象是否有“withCredentials”属性
    // “withCredentials”仅存在于XMLHTTPRequest2对象里
    if ("withCredentials" in xhr){
        xhr.open(method, url, true);
        // 检查是否支持XDomainRequest,IE8和IE9支持
        // XDomainRequest仅存在于IE中,是IE用于支持CORS请求的方式
    } else if (typeof XDomainRequest != "undefined"){
        xhr = new XDomainRequest();
        xhr.open(method, url);
    } else {
        // 否则,浏览器不支持CORS
        xhr = null;
    }
    return xhr;
}


var xhr = createCORSRequest('GET', "http://www.somewhere-else.com/page/");
if (!xhr) {
    throw new Error('CORS not supported');
} else {
    xhr.onload = function(){
        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
            alert(xhr.responseText);
        } else {
            alert("Request was unsuccessful: " + xhr.status);
        }
    };
    xhr.send();
}

现在如果直接使用上面的脚本进行请求,会看到浏览器里控制台的报错如下:

错误显示的很明显,这是因为我们还未设置Access-Control-Allow-Origin头。

接下来,需要服务器设置Access-Control-Allow-Origin头。

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

 HTTP 头的设置方法有很多,http://enable-cors.org/这篇文章里对各种服务器和语言的设置都有详细的介绍,下面我们主要介绍Apache和PHP里的设置方法。

Apache:Apache需要使用mod_headers模块来激活HTTP头的设置,它默认是激活的。

你只需要在Apache配置文件的<Directory>, <Location>, <Files>或<VirtualHost>的配置里加入以下内容即可:

Header set Access-Control-Allow-Origin *  

PHP:只需要使用如下的代码设置即可:

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

以上的配置的含义是允许任何域发起的请求都可以获取当前服务器的数据。当然,这样有很大的危险性,恶意站点可能通过XSS攻击我们的服务器。

所以我们应该尽量有针对性的对限制安全的来源,例如下面的设置使得只有 http://blog.csdn.net 这个域才能跨域访问服务器的API。

Access-Control-Allow-Origin: http://blog.csdn.net

从浏览器都支持来看,CORS将成为未来跨域访问的标准解决方案。

无论是自己服务器间的跨域访问,还是开放平台为第三方提供API,都将采用这种统一的解决方案,因为它简单、高效,受到所有主流浏览器的支持。

它非常重要,也会让我们的网络变得更加开放。

关于本方法,参考了资料:http://www.cnblogs.com/yuzhongwusan/p/3677955.html

以往的解决方案

在 CORS 出现以前,要实现跨域 Ajax 通信颇费一些周折。

开发人员想出了一些办法,利用 DOM 中能够执行跨域请求的功能,在不依赖 XHR 对象的情况下也能发送某种请求。

虽然 CORS 技术已经无处不在,但开发人员自己发明的这些技术仍然被广泛使用,毕竟这样不需要修改服务器端代码。

常见的有如下几种:

1 图像ping

2 JSONP

3 comet(SSE)

4 web Sockets

具体情况,请阅读 Professional JavaScript for Web Developers

18 安全性

对于未被授权系统有权访问某个资源的情况,我们称之为 CSRF(Cross-Site Request Forgery,跨站点请求伪造)。

未被授权系统会伪装自己,让处理请求的服务器认为它是合法的。 

比如:

/getuserinfo.php?id=23

如果是向这个 URL 发送请求,可以想象结果会返回 ID 为 23 的用户的某些数据。

谁也无法保证别人不会将这个 URL 的用户 ID 修改为 24、 56 或其他值。

因此, getuserinfo.php 文件必须知道请求者是否真的有权限访问要请求的数据;否则,你的服务器就会门户大开,任何人的数据都可能被泄漏出去。

为确保通过 XHR 访问的 URL 安全,通行的做法就是验证发送请求者是否有权限访问相应的资源。
有下列几种方式可供选择。

 要求以 SSL 连接来访问可以通过 XHR 请求的资源。
 要求每一次请求都要附带经过相应算法计算得到的验证码

原文地址:https://www.cnblogs.com/lijy/p/6510154.html