原生ajax总结

ajax介绍

  1. ajax是一种无刷新网页得和服务器交换数据的一种技术。
  2. AJAX是不能跨域的,如需跨域,可以使用document.domain=’a.com’;或者使用服务器代理,代理XMLHttpRequest文件。
    • 跨域有许多解决方案,jsonp、 iframe、window.name、window.postMessage、服务器上设置代理页面。
  3. 其由来和历史原因我们这里我们不探讨,我们来看下ajax的优缺点
    • 优点:
      • 通过异步模式,提升了用户体验
      • 优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用
      • Ajax在客户端运行,承担了一部分本来由服务器承担的工作,减少了大用户量下的服务器负载。
    • 缺点:
      • ajax不支持浏览器back按钮。
      • 安全问题 AJAX暴露了与服务器交互的细节。
      • 对搜索引擎的支持比较弱。
      • 破坏了程序的异常机制。
      • 不容易调试。
  4. 这里我们再来看看http状态码,以便于我们分析ajax请求的结果。
    • 100 Continue 继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息
    • 200 OK 正常返回信息
    • 201 Created 请求成功并且服务器创建了新的资源
    • 202 Accepted 服务器已接受请求,但尚未处理
    • 301 Moved Permanently 请求的网页已永久移动到新位置。
    • 302 Found 临时性重定向。
    • 303 See Other 临时性重定向,且总是使用 GET 请求新的 URI。
    • 304 Not Modified 自从上次请求后,请求的网页未修改过。
    • 400 Bad Request 服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求。
    • 401 Unauthorized 请求未授权。
    • 403 Forbidden 禁止访问。
    • 404 Not Found 找不到如何与 URI 相匹配的资源。
    • 500 Internal Server Error 最常见的服务器端错误。
    • 503 Service Unavailable 服务器端暂时无法处理请求(可能是过载或维护)。

原生ajax请求数据:

创建 XMLHttpRequest 对象

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

创建Ajax对象:

1
2
3
4
5
//IE6以上
var oAjax = new XMLHttpRequest();

//IE6
var oAjax =new ActiveXObject("Microsoft.XMLHTTP")

鉴于IE6浏览器基本已经淘汰,我们后面的内容都不考虑其情况。

连接服务器

1
oAjax.open(方法, url, isAsyn)
  • isAsyn(是否异步)
    • true:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。
    • false:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。

发送请求send()

1
oAjax.send(data);

GET 还是 POST?两者的区别?何时使用 post

  • GET:一般用于信息获取,使用URL传递参数,对所发送信息的数量也有限制,一般在2000个字符
  • POST:一般用于修改服务器上的资源,对所发送的信息没有限制。
  • GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值,也就是说Get是通过地址栏来传值,而Post是通过提交表单来传值。
  • 然而,在以下情况中,请使用 POST 请求:
    • 无法使用缓存文件(更新服务器上的文件或数据库)
    • 向服务器发送大量数据(POST 没有数据量限制)
    • 发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠

setRequestHeader()添加http 头

  • 如果需要像 HTML 表单那样 POST 数据,请使用 setRequestHeader() 来添加 HTTP 头。然后在 send() 方法中规定您希望发送的数据:
1
2
3
xmlhttp.open("POST","ajax_test.asp",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Bill&lname=Gates");
  • 这里method,上传方式只能选择 post 。
  • enctype这个属性管理的是表单的MIME,参数规定了在发送到服务器之前应该如何对表单数据进行编码方式。
  • 常见的参数有application/x-www-form-urlencodedtext/plain和示例中的multipart/form-data,因为上传的文件都是非纯文本传输,所以指定的类型必须只能是multipart/form-data
    • 其中①application/x-www-form-urlencoded是默认值,
      大家可能在AJAX里见过这个:xmlHttp.setRequestHeader(“Content-Type”,”application/x-www-form-urlencoded”);
      这两个要做的是同一件事情,就是设置表单传输的编码。在AJAX里不写有可能会报错,但是在HTML的form表单里是可以不写enctype=”application/x-www-form-urlencoded”的,因为默认HTML表单就是这种传输编码类型。
      • 而②multipart-form-data是用来指定传输数据的特殊类型的,主要就是我们上传的非文本的内容,比如图片或者mp3等等。
      • ③text/plain是纯文本传输的意思,在发送邮件时要设置这种编码类型,否则会出现接收时编码混乱的问题,网络上经常拿text/plain和text/html做比较,其实这两个很好区分,前者用来传输纯文本文件,后者则是传递html代码的编码类型,在发送头文件时才用得上。
      • ①和③都不能用于上传文件,只有multipart/form-data才能完整的传递文件数据。
方法 描述
setRequestHeader(header,value) 向请求添加 HTTP 头。
* header: 规定头的名称
* value: 规定头的值。

接收返回的数据

1
2
3
oAjax.onreadystatechange = function(){
console.log(oAajax.readyState)
}

readyState属性 状态 有5个可取值: 0=未初始化 ,1=启动 2=发送,3=接收,4=完成。
当readyState属性发生变化的时候,便会触发一次readystatechange 事件。我们可以通过监听这个事件,当数据准备完毕之后,处理数据。

1
2
3
4
5
6
7
8
9
10
11
12
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
console.log(xhr.statusText);
} else {
console.log("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("get", "example.txt", true);
xhr.send(null);

XHR对象

  • XMLHttpRequest这个对象的属性:
    • onreadystatechange 每次状态改变所触发事件的事件处理程序。
    • responseText 从服务器进程返回数据的字符串形式。
    • responseXML 从服务器进程返回的DOM兼容的文档数据对象。
    • status 从服务器返回的数字代码,比如常见的404(未找到)和200(已就绪)
    • statusText 伴随状态码的字符串信息

避免缓存

对 Ajax 请求进行缓存的浏览器特性都快被我们忘记了。例如,IE 就默认是这样。jQuery 默认清除浏览器缓存。在纯 Ajax 也能达到该目的:

1
2
var bustCache = '?' + new Date().getTime();
oReq.open('GET', url , true);

查看 jQuery 文档,可知道 jQuery 在每个请求(GET)后面追加一个时间戳作为查询字符串。
这在某个程度上让请求变得独一无二,并避免浏览器缓存。每当你触发 HTTP Ajax 请求,你能看到类似如下请求:
image

封装ajax

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
* AJAX函数封装
* @param {string} url 请求地址(必须)
* @param {object} options 发送请求的选项参数
* @config {string} [options.type] 请求发送的类型。默认为GET。
* @config {Object} [options.data] 需要发送的数据。
* @config {Function} [options.onsuccess] 请求成功时触发,function(oAjax.responseText, oAjax)。(必须)
* @config {Function} [options.onfail] 请求失败时触发,function(oAjax)。(oAJax为XMLHttpRequest对象)
*
*@returns {XMLHttpRequest} 发送请求的XMLHttpRequest对象
*/
function ajax(url, options) {
//1.创建ajax对象
var oAjax = null;
/**
* 此处必须需要使用window.的方式,表示为window对象的一个属性.不存在时值为undefined,进入else
* 若直接使用XMLHttpRequest,在不支持的情况下会报错
**/
if (window.XMLHttpRequest) {
//IE6以上
oAjax = new XMLHttpRequest();
} else {
oAjax = new ActiveXObject("Microsoft.XMLHTTP");
}

//2.连接服务器
//open(方法,url,是否异步)
var param = ""; //请求参数。
//只有data存在,且为对象使才执行
var data = options.data ? options.data : -1; //缓存data
if (typeof (data) === "object") {
for (var key in data) { //请求参数拼接
if (data.hasOwnProperty(key)) {
param += key + "=" + data[key] + "&";
}
}
param.replace(/&$/, "");
} else {
param = "timestamp=" + new Date().getTime();
}

//3.发送请求
var type = options.type ? options.type.toUpperCase() : "GET";
if (type === "GET") {
oAjax.open("GET", url + "?" + param, true);
oAjax.send();
} else {
oAjax.open("POST", url, true);
oAjax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
oAjax.send(param);
}

//4.接收返回
//OnRedayStateChange事件
oAjax.onreadystatechange = function () {
if (oAjax.readyState === 4) {
if (oAjax.status === 200) {
//请求成功。形参为获取到的字符串形式的响应数据
options.onsuccess(oAjax.responseText, oAjax);
} else {
//先判断是否存在请求失败函数
//存在时,形参为XMLHttpRequest对象,便于进行错误进行处理
if (options.onfail) {
options.onfail(oAjax);
}
}
}
};
return oAjax;//发送请求的XMLHttpRequest对象
}