浅聊一下
提到AJAX,好像有点熟悉...
没错,在上一篇文章里,我们讲了如何使用AJAX来请求数据
在本篇文章中,我们将对其进行一个升华,带领大家来手写一个AJAX...
手写AJAX
先给大家展示代码,再来一步步讲解
js
function getDataByAjax(url) {
//promise 是 es6 提供的一个类,实例化的时候 立即执行传给他的执行器
//executor new Promise同步执行
return new Promise((resolve, reject) => {
console.log('11111');
//异步任务的容器
// setTimeout(()=>{
// resolve('5555')
// },2000)
//浏览器的兼容性 IE 低版本不支持XMLHttpRequest
const xhr = XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject('Microsoft.XMLHttp');
// 主动请求数据 open:打开
console.log(xhr.readyState);//0 表示 XHR 对象已经被创建,但尚未调用 open() 方法
xhr.open('GET', url, false);
console.log(xhr.readyState);//1 http请求通道打开
xhr.onreadystatechange = function () {
console.log(xhr.readyState);//完成所有数据的传输
if (xhr.readyState !== 4) {
return;
}
//200成功 304 Not Modifyed 性能优化 服务器端资源
// 在多次请求中并没有改变 (updata_time 文件没修改返回304) 304响应头 不传输响应体
// 前端拿到304怎么办? 前端会去浏览器缓存里拿之前的结果 协商缓存
if (xhr.status === 200 || xhr.status === 304) {
resolve(xhr.responseText)
} else {
reject(xhr.responseText)
}
}
xhr.send();
console.log(xhr.readyState);
})
}
我们知道,获取数据是需要耗时的,所以我们所执行的方法是一个异步任务
要在等待请求完毕后继续执行任务,那我们就得用到Promise,同样的要是有掘友对于Promise不太熟悉,可以去看我之前的文章(Promise:解决JavaScript异步编程难题 - 掘金 (juejin.cn))
js
const xhr = XMLHttpRequest
?new XMLHttpRequest()
: new ActiveXObject('Microsoft.XMLHttp');
我们在上一篇文章中使用的只有XMLHttpRequest
,为什么这里还需要用到三元运算符呢?
在这里,我们使用这种方法来提高浏览器的兼容性,在一些旧版本的IE浏览器中,没有全局的XMLHttpRequest对象, 则使用 new ActiveXObject('Microsoft.XMLHttp')
来创建一个 ActiveXObject 对象。
js
xhr.onreadystatechange = function () {
console.log(xhr.readyState);//完成所有数据的传输
if (xhr.readyState !== 4) {
return;
}
//200成功 304 Not Modifyed 性能优化 服务器端资源
// 在多次请求中并没有改变 (updata_time 文件没修改返回304) 304响应头 不传输响应体
// 前端拿到304怎么办? 前端会去浏览器缓存里拿之前的结果 协商缓存
if (xhr.status === 200 || xhr.status === 304) {
resolve(xhr.responseText)
} else {
reject(xhr.responseText)
}
}
在if判断中,判断状态码如果不为4.则说明数据没有完成传输,直接return
当xhr.status === 200 时,说明此时请求成功,那么当他等于304又代表了什么呢?
304 代表多次获取数据时,数据并没有发生改变
那么当前端拿到304的时候该怎么办呢?
应该去找到之前的数据,前端会去浏览器缓存里拿之前的结果
响应成功,通过 resolve(xhr.responseText)
将响应文本传递给 Promise 的 resolve
函数。如果请求失败,通过 reject(xhr.responseText)
将响应文本传递给 Promise 的 reject
函数。
调用getDataByAjax()
接下来我们来调用getDataByAjax()
js
(async function () {
const p = getDataByAjax('https://api.github.com/users/shunwuyu/repos')
console.log('2222');
console.log(p);//panding 状态
//await 后面是一个promise对象
try {
const data = await p//卡在这里
console.log('3333');
console.log(p);//fullfilled
console.log(data);
} catch (error) {
console.log(err);
}
})()
const p = getDataByAjax('https://api.github.com/users/shunwuyu/repos')
:调用getDataByAjax
函数,该函数返回一个 Promise 对象,代表异步操作。p
变量将包含这个 Promise。console.log('2222');
:输出 '2222',这是在异步操作执行的过程中同步执行的代码。console.log(p);
:输出 Promise 对象,此时 Promise 处于挂起(pending)状态,因为异步操作尚未完成。const data = await p
:通过await
关键字等待p
Promise 对象的解决。这会阻塞后续代码的执行,直到 Promise 状态变为已解决(fulfilled)或者拒绝(rejected)。console.log('3333');
:当 Promise 对象解决后,输出 '3333'。console.log(p);
:输出 Promise 对象,此时 Promise 处于已解决状态(fulfilled)。
我们来看结果:
结尾
今天手写的AJAX着实优雅,把他写给面试官,相信他会给你嘎嘎加分