Ajax的工做原理至关于在用户和服务器之间加了一个中间层(ajax引擎),使用户操做与服务器响应异步化。并非全部的用户请求都提交给服务器,像—些数据验证(好比判断用户是否输入了数据)和数据处理(好比判断用户输入数据是不是数字)等都交给Ajax引擎本身来作, 只有肯定须要从服务器读取新数据时再由Ajax引擎代为向服务器提交请求。把这些交给了Ajax引擎,用户操做起来也就感受更加流畅了。前端
看了网上前辈们写的资料,我本身总结概括ajax的原理和流程以下:node
这个是ajax核心的对象, 如下代码是chrome浏览器和兼容IE浏览器的版本jquery
var ajax = {};
ajax.httpRequest = function () {
//判断是否支持XMLHttpRequest对象
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
}
//兼容IE浏览器
var versions = [
"MSXML2.XmlHttp.6.0",
"MSXML2.XmlHttp.5.0",
"MSXML2.XmlHttp.4.0",
"MSXML2.XmlHttp.3.0",
"MSXML2.XmlHttp.2.0",
"Microsoft.XmlHttp"
];
//定义局部变量xhr,储存IE浏览器的ActiveXObject对象
var xhr;
for (var i = 0; i < versions.length; i++) {
try {
xhr = new ActiveXObject(versions[i]);
break;
} catch (e) {
}
}
return xhr;
};
复制代码
1.无刷新更新数据。
2.异步与服务器通讯。
3.前端和后端负载平衡。
4.基于标准被普遍支持。
5.界面与应用分离。
复制代码
1.AjAX干掉了Back和加入收藏书签功能,即对浏览器机制的破坏。
2.AJAX的安全问题。
3.由于网络延迟须要给用户提供必要提示
复制代码
Ajax(Asynchronous JavaScript and XML)不是指一种单一的技术,而是有机地利用了一系列相关的技术。虽然其名称包含XML,但实际上数据格式能够由JSON代替,进一步减小数据量,造成所谓的AJAJ。为了使用JavaScript向服务器发出 HTTP 请求,须要一个提供此功能的类的实例。这就是XMLHttpRequest的由来。这样的类最初是在Internet Explorer中做为一个名为XMLHTTP的ActiveX对象引入的。而后,Mozilla,Safari和其余浏览器,实现一个XMLHttpRequest类,支持Microsoft的原始ActiveX对象的方法和属性。同时微软也实现了XMLHttpRequest。ios
(1)设置请求参数(请求方式,请求页面的相对路径,是否异步)
(2)设置回调函数,一个处理服务器响应的函数,使用 onreadystatechange ,相似函数指针
(3)获取异步对象的readyState 属性:该属性存有服务器响应的状态信息。每当 readyState 改变时,onreadystatechange 函数就会被执行。
(4)判断响应报文的状态,若为200说明服务器正常运行并返回响应数据,
(5)读取响应数据,能够经过 responseText 属性来取回由服务器返回的数据。
复制代码
onreadystatechangees6
一个JavaScript函数对象,当readyState属性改变时会调用它。回调函数会在user interface线程中调用。ajax
readyStatechrome
HTTP 请求的状态.当一个 XMLHttpRequest 初次建立时,这个属性的值从 0 开始,直到接收到完整的 HTTP 响应,这个值增长到 4。json
5个状态中每个都有一个相关联的非正式的名称,下表列出了状态、名称和含义:axios
状态 | 名称 | 描述 |
---|---|---|
0 | Uninitialized | 初始化状态。XMLHttpRequest 对象已建立或已被 abort() 方法重置。 |
1 | Open | open() 方法已调用,可是 send() 方法未调用。请求尚未被发送。 |
2 | Sent | Send() 方法已调用,HTTP 请求已发送到 Web 服务器。未接收到响应。 |
3 | Receiving | 全部响应头部都已经接收到。响应体开始接收但未完成。 |
4 | Loaded | HTTP 响应已经彻底接收。 |
readyState 的值不会递减,除非当一个请求在处理过程当中的时候调用了 abort() 或 open() 方法。每次这个属性的值增长的时候,都会触发 onreadystatechange 事件句柄。后端
responseText
目前为止为服务器接收到的响应体(不包括头部),或者若是尚未接收到数据的话,就是空字符串。
若是 readyState 小于 3,这个属性就是一个空字符串。当 readyState 为 3,这个属性返回目前已经接收的响应部分。若是 readyState 为 4,这个属性保存了完整的响应体。
若是响应包含了为响应体指定字符编码的头部,就使用该编码。不然,假定使用 Unicode UTF-8。
responseXML
对请求的响应,解析为 XML 并做为 Document 对象返回。
status
由服务器返回的 HTTP 状态代码,如 200 表示成功,而 404 表示 "Not Found" 错误。当 readyState 小于 3 的时候读取这一属性会致使一个异常。
statusText
这个属性用名称而不是数字指定了请求的 HTTP 的状态代码。也就是说,当状态为 200 的时候它是 "OK",当状态为 404 的时候它是 "Not Found"。和 status 属性同样,当 readyState 小于 3 的时候读取这一属性会致使一个异常。
abort()
取消当前响应,关闭链接而且结束任何未决的网络活动。
这个方法把 XMLHttpRequest 对象重置为 readyState 为 0 的状态,而且取消全部未决的网络活动。例如,若是请求用了太长时间,并且响应再也不必要的时候,能够调用这个方法。
getAllResponseHeaders()
把 HTTP 响应头部做为未解析的字符串返回。
若是 readyState 小于 3,这个方法返回 null。不然,它返回服务器发送的全部 HTTP 响应的头部。头部做为单个的字符串返回,一行一个头部。每行用换行符 "\r\n" 隔开。
getResponseHeader()
返回指定的 HTTP 响应头部的值。其参数是要返回的 HTTP 响应头部的名称。可使用任何大小写来制定这个头部名字,和响应头部的比较是不区分大小写的。
该方法的返回值是指定的 HTTP 响应头部的值,若是没有接收到这个头部或者 readyState 小于 3 则为空字符串。若是接收到多个有指定名称的头部,这个头部的值被链接起来并返回,使用逗号和空格分隔开各个头部的值。
open()
初始化一个请求. 该方法用于JavaScript代码中;若是是本地代码, 使用 openRequest())方法代替.
注意: 在一个已经激活的request下(已经调用open()或者openRequest()方法的request)再次调用这个方法至关于调用了abort()方法。
参数
请求所使用的HTTP方法; 例如 "GET", "POST", "PUT", "DELETE"等. 若是下个参数是非HTTP(S)的URL,则忽略该参数.
该请求所要访问的URL
一个可选的布尔值参数,默认为true,意味着是否执行异步操做,若是值为false,则send()方法不会返回任何东西,直到接受到了服务器的返回数据。若是为值为true,一个对开发者透明的通知会发送到相关的事件监听者。这个值必须是true,若是multipart 属性是true,不然将会出现一个意外。
用户名,可选参数,为受权使用;默认参数为空string.
密码,可选参数,为受权使用;默认参数为空string.
send()
发送 HTTP 请求,使用传递给 open() 方法的参数,以及传递给该方法的可选请求体。
setRequestHeader()
向一个打开但未发送的请求设置或添加一个 HTTP 请求(设置请求头)。 参数
将要被赋值的请求头名称
给指定的请求头赋的值
ajax.send = function (url, callback, method, data, async) {
//默认异步
if (async === undefined) {
async = true;
}
var httpRequest = ajax.httpRequest();
//初始化HTTP请求
httpRequest.open(method, url, async);
//onreadystatechange函数对象
httpRequest.onreadystatechange = function () {
//readyState 的值等于4,从服务器拿到了数据
if (httpRequest.readyState == 4) {
//回调服务器响应数据
callback(httpRequest.responseText)
}
};
if (method == 'POST') {
//给指定的HTTP请求头赋值
httpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
}
//发送HTTP请求
httpRequest.send(data);
};
//实现GET请求
ajax.get = function (url, data, callback, async) {
var query = [];
for (var key in data) {
query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
}
ajax.send(url + (query.length ? '?' + query.join('&') : ''), callback, 'GET', null, async)
};
//实现POST请求
ajax.post = function (url, data, callback, async) {
var query = [];
for (var key in data) {
query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
}
ajax.send(url, callback, 'POST', query.join('&'), async)
};
复制代码
$.ajax({
type: "", 请求方式
url: "", // 请求路径
async: true, // 默认是异步
data: JSON.stringify({ obj }),
contentType: 'application/json;charset=utf-8', // 设置contentType
success: function(res) {
console.log(res)
},
error: function(err) {
console.log(err)
}
)
复制代码
一、key添加双引号
二、末尾没有分号
三、同一个对象不容许有两个同名属性
复制代码
序列化
JSON.stringify() // JSON对象转换成JSON字符串
JSON.parse() // JSON对象转换成JSON字符串
复制代码
fetch号称是ajax的替代品,它的API是基于Promise设计的,旧版本的浏览器不支持Promise,须要使用polyfill es6-promise
// 原生XHR
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText) // 从服务器获取数据
}
}
xhr.send()
// fetch
fetch(url)
.then(response => {
if (response.ok) {
response.json()
}
})
.then(data => console.log(data))
.catch(err => console.log(err))
复制代码
在MDN上,讲到它跟jquery ajax的区别,这也是fetch很奇怪的地方:
当接收到一个表明错误的 HTTP 状态码时,从 fetch()返回的 Promise 不会被标记为 reject, 即便该 HTTP 响应的状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (可是会将 resolve 的返回值的 ok 属性设置为 false ), 仅当网络故障时或请求被阻止时,才会标记为 reject。 默认状况下, fetch 不会从服务端发送或接收任何 cookies, 若是站点依赖于用户 session,则会致使未经认证的请求(要发送 cookies,必须设置 credentials 选项).
忽然感受这还不如jquery ajax好用呢?别急,再搭配上async/await将会让咱们的异步代码更加优雅:
async function test() {
let response = await fetch(url);
let data = await response.json();
console.log(data)
}
复制代码
看起来是否是像同步代码同样?简直完美!好吧,其实并不完美,async/await是ES7的API,目前还在试验阶段,还须要咱们使用babel进行转译成ES5代码。
还要提一下的是,fetch是比较底层的API,不少状况下都须要咱们再次封装。 好比:
// jquery ajax
$.post(url, {name: 'test'})
// fetch
fetch(url, {
method: 'POST',
body: Object.keys({name: 'test'}).map((key) => {
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
}).join('&')
})
复制代码
因为fetch是比较底层的API,因此须要咱们手动将参数拼接成'name=test'的格式,而jquery ajax已经封装好了。因此fetch并非开箱即用的。
另外,fetch还不支持超时控制。
哎呀,感受fetch好垃圾啊,,还须要继续成长。。
axios是尤雨溪大神推荐使用的,它也是对原生XHR的封装。它有如下几大特性:
简单使用
axios({
method: 'GET',
url: url,
})
.then(res => {console.log(res)})
.catch(err => {console.log(err)})
复制代码
并行开发
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// Both requests are now complete
}));
复制代码