一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
AJAX原理
Ajax
的原理简单来说是在用户和服务器之间加了—个中间层(AJAX
引擎),通过XmlHttpRequest
对象来向服务器发异步请求,从服务器获得数据,然后用javascrip
t来操作DOM
而更新页面。使用户操作与服务器响应异步化。Ajax
的过程只涉及JavaScript
、XMLHttpRequest
和DOM
。XMLHttpRequest
是ajax
的核心机制
XMLHttpRequest
(XHR)对象用于与服务器交互。通过 XMLHttpRequest
可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest
可以用于获取任何类型的数据,而不仅仅是 XML。甚至支持 HTTP
以外的协议(包括 file:// 和 FTP),尽管可能受到更多出于安全等原因的限制。
/** 1. 创建Ajax对象 **/
var xhr = window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');// 兼容IE6及以下版本
/** 2. 配置 Ajax请求 **/
xhr.open('get', url, true)
/** 3. 发送请求 **/
xhr.send(null); // 严谨写法
/** 4. 监听请求,接受响应 **/
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
success(xhr.responseText);
} else {
/** false **/
fail && fail(xhr.status);
}
}
}
-
onreadystatechange
:当readyState
属性发生变化时,调用的事件处理函数 -
readyState
:值 状态 描述 0
UNSENT
代理被创建,但尚未调用 open() 方法。 1
OPENED
open()
方法已经被调用。2
HEADERS_RECEIVED
send()
方法已经被调用,并且头部和状态已经可获得。3
LOADING
下载中; responseText
属性已经包含部分数据。4
DONE
下载操作已完成。 -
response
:返回的包含整个响应实体 -
responseText
:返回一个DOMString
,该DOMString
包含对请求的响应,如果请求未成功或尚未发送,则返回null
。 -
responseType
:一个用于定义响应类型的枚举值(enumerated value)。类型 解释 “ ” 空的 responseType
字符串与默认类型"text"
相同。"arraybuffer" response
是一个包含二进制数据的 JavaScriptArrayBuffer
。"blob" response
是一个包含二进制数据的Blob
对象。"document" response
是一个 HTMLDocument或XMLDocument"json" response
是通过将接收到的数据内容解析为JSON的JS对象"text" response
是DOMString
对象中的文本。"ms-stream" response
是流式下载的一部分;此响应类型仅允许用于下载请求,并且仅受 Internet Explorer 支持。 -
status
:返回一个无符号短整型(unsigned short
)数字,代表请求的响应状态。var xhr = new XMLHttpRequest(); console.log('UNSENT', xhr.status); xhr.open('GET', '/server', true); console.log('OPENED', xhr.status); xhr.onprogress = function () { console.log('LOADING', xhr.status); }; xhr.onload = function () { console.log('DONE', xhr.status); }; xhr.send(null); /** * 输出如下: * * UNSENT(未发送) 0 * OPENED(已打开) 0 * LOADING(载入中) 200 * DONE(完成) 200 */
-
withCredentials
:一个布尔值,用来指定跨域Access-Control
请求是否应当带有授权信息,如 cookie 或授权 header 头。xhr.withCredentials=true
-
upload
:代表上传进度
ajax 有那些优缺点?
-
优点:
- 通过异步模式,提升了用户体验.
- 优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用.
Ajax
在客户端运行,承担了一部分本来由服务器承担的工作,减少了大用户量下的服务器负载。Ajax
可以实现动态不刷新(局部刷新)
-
缺点:
- 安全问题
AJAX
暴露了与服务器交互的细节。 - 对搜索引擎的支持比较弱。
- 不容易调试。
- 安全问题
Promise封装Ajax
promise 封装实现:
// promise 封装实现:
function getJSON(url) {
// 创建一个 promise 对象
let promise = new Promise(function(resolve, reject) {
let xhr = new XMLHttpRequest();
// 新建一个 http 请求
xhr.open("GET", url, true);
// 设置状态的监听函数
xhr.onreadystatechange = function() {
if (this.readyState !== 4) return;
// 当请求成功或失败时,改变 promise 的状态
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
// 设置错误监听函数
xhr.onerror = function() {
reject(new Error(this.statusText));
};
// 设置响应的数据类型
xhr.responseType = "json";
// 设置请求头信息
xhr.setRequestHeader("Accept", "application/json");
// 发送 http 请求
xhr.send(null);
});
return promise;
}
JQ Ajax、Axios、Fetch的核心区别
JQuery Ajax
Ajax
前后端数据通信「同源、跨域」
// 用户登录 -> 登录成功 -> 获取用户信息
/* 回调地狱 */
$.ajax({
url: 'http://127.0.0.1:8888/user/login',
method: 'post',
data: Qs.stringify({
account: '18310612838',
password: md5('1234567890')
}),
success(result) {
if (result.code === 0) {
// 登录成功
$.ajax({
url: 'http://127.0.0.1:8888/user/list',
method: 'get',
success(result) {
console.log(result);
}
});
}
}
});
优缺点:
- 本身是针对
MVC
的编程,不符合现在前端MVVM
的浪潮 - 基于原生的
XHR
开发,XHR
本身的架构不清晰,已经有了fetch
的替代方案 JQuery
整个项目太大,单纯使用ajax
却要引入整个JQuery
非常的不合理(采取个性化打包的方案又不能享受CDN服务)
Axios
Axios
也是对ajax
的封装,基于Promise
管理请求,解决回调地狱问题
axios({
method: 'post',
url: '/user/login',
data: {
username: 'name',
password: 'password'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// 或使用 async await
(async function () {
let result1 = await axios.post('/user/login', {
username: 'name',
password: 'password'
});
let result2 = await axios.get('/user/list');
console.log(result1, result2);
})();
优缺点:
- 从浏览器中创建
XMLHttpRequest
- 从
node.js
发出http
请求 - 支持
Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 取消请求
- 自动转换
JSON
数据 - 客户端支持防止
CSRF/XSRF
Fetch
Fetch
是ES6
新增的通信方法,不是ajax
,但是他本身实现数据通信,就是基于promise
管理的
try {
let response = await fetch(url, options);
let data = response.json();
console.log(data);
} catch(e) {
console.log("Oops, error", e);
}
示例:
(async function () {
let result = await fetch('http://127.0.0.1:8888/user/login', {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: Qs.stringify({
name: 'name',
password: 'password'
})
})
let data = result.json();
console.log(data)
let result2 = await fetch('http://127.0.0.1:8888/user/list').then(response => {
return response.json();
});
console.log(result2);
})();
优缺点:
fetcht
只对网络请求报错,对400
,500
都当做成功的请求,需要封装去处理fetch
默认不会带cookie
,需要添加配置项fetch
不支持abort
,不支持超时控制,使用setTimeout
及Promise.reject
的实现的超时控制并不能阻止请求过程继续在后台运行,造成了量的浪费fetch
没有办法原生监测请求的进度,而XHR可以