19 Ajax总结
Ajax的原理简单来说是在用户和服务器之间加了—个中间层(AJAX引擎),通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面。使用户操作与服务器响应异步化。这其中最关键的一步就是从服务器获得请求数据Ajax的过程只涉及JavaScript、XMLHttpRequest和DOM。XMLHttpRequest是ajax的核心机制
补充(现代做法):实际开发已基本用
fetchAPI 取代手写XMLHttpRequest,它基于 Promise,配合async/await写法更简洁;需要请求超时 / 取消时用AbortController。示例:const res = await fetch(url); const data = await res.json();。注意fetch默认不带 cookie(需credentials: 'include'),且仅在网络错误时 reject,HTTP 4xx/5xx 不会 reject,要自行判断res.ok。
19.1 Ajax 有那些优缺点
优点:
- 通过异步模式,提升了用户体验.
- 优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用.
Ajax在客户端运行,承担了一部分本来由服务器承担的工作,减少了大用户量下的服务器负载。Ajax可以实现动态不刷新(局部刷新)
缺点:
- 安全问题
AJAX暴露了与服务器交互的细节。 - 对搜索引擎的支持比较弱。
- 不容易调试。
19.2 关于http,XMLHttpRequest,Ajax的关系
http是浏览器和web服务器交换数据的协议,规范XMLHttpRequest是一个JS对象,是浏览器实现的一组api函数,使用这些函数,浏览器再通过http协议请求和发送数据。Ajax是一种技术方案,但并不是一种新技术,它最核心的就是依赖浏览器提供的XMLHttpRequest对象。用一句话来概括就是我们使用XMLHttpRequest对象来发送一个Ajax请求。
19.3 XMLHttpRequest的发展历程是怎样的?
它最开始只是微软浏览器提供的一个接口,后来各大浏览器纷纷效仿也提供了这个接口,再后来W3C对它进行了标准化,提出了XMLHttpRequest标准。标准又分为Level 1和Level 2。
Level 2相对于Level 1做了很大的改进,具体来说是:
- 可以设置
HTTP请求的超时时间。 - 可以使用
FormData对象管理表单数据。 - 可以上传文件。
- 可以请求不同域名下的数据(跨域请求)。
- 可以获取服务器端的二进制数据。
- 可以获得数据传输的进度信息。
19.4 使用XMLHttpRequest封装一个get和post请求
get请求 :
核心就四步:
var xhr = new XMLHttpRequest()xhr.open('GET', 'http://www.example.com/api/getname', true)xhr.onreadystatechange = function () {}xhr.send()
让我们来封装一个简易版的:
/*
* xhr的get请求
* @param url: 请求地址
* @param params: 请求参数
* @param onSuccess: 成功回调函数
* @param onError: 失败回调函数
*/
function xhrGet (url, params = {}, onSuccess, onError) {
// 兼容IE6
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
let paramString = formatParams(params);
// xhr.open的第三个参数isAsync:是否异步
xhr.open('GET', `${url}${paramString}`, true);
xhr.onreadystatechange = function () {
// console.log(e);
console.log(this);
if (this.readyState === 4) {
if (this.status >= 200 && this.status < 300) {
onSuccess(this.response);
} else {
onError(this.response)
}
}
}
xhr.send();
}
// 处理参数:如将{name: 'lindaidai'}转为'?name=lindaidai'
function formatParams (params) {
var paramString = Object.keys(params).map(key => {
return `${key}=${encodeURIComponent(params[key])}`
}).join('&');
return paramString ? `?${paramString}` : ''
}
(当然上面的兼容IE6估计现在考的不多了,而且我这种写法其实也没啥用,因为如果真是在IE6下的话,后面的Object.keys()等方法也用不了了)
需要注意的是两种状态,一个是readyState,一个是status。
readyState请求状态:
0(未初始化):还没有调用open()方法。1(载入):已调用send()方法,正在发送请求。2(载入完成):send()方法完成,已收到全部响应内容。3(解析):正在解析响应内容。4(完成):响应内容解析完成,可以在客户端调用。
status结果状态码:
0:如果状态是UNSENT或OPENED;或者如果错误标签被设置(例如跨域时)200成功- 其它
HTTP状态码
post请求:
function xhrPost (url, params, onSuccess, onError) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
// ajax的默认请求ContentType:text/plain(纯文本)
xhr.setRequestHeader("Content-Type", "application-x-www-form-urlencode");
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status >= 200 && this.status < 300) {
onSuccess(this.response);
} else {
onError(this.response);
}
}
}
xhr.send(params);
}
