前言
在现代的Web开发中,异步请求是不可或缺的一部分,而AJAX
(Asynchronous JavaScript and XML)是实现异步请求的重要技术。在上篇文章中我们详细学习了实现AJAX的三种方法。今天为了更好地深入理解AJAX
,我们将通过手写一个AJAX
请求的过程,并使用Promise
进行封装,使其中过程更真实且易于理解。那么话不多说,开启实战!
手写AJAX代码
在详细介绍之前,先来看我们今天的完整代码,接下来我会为大家逐步剖析这份代码然后进行详解。
完整代码
js
function getDataByAjax(url) {
return new Promise((resolve, reject) => {
console.log('1111');
// 浏览器的兼容性 ie 低版本不支持XMLHttpRequest
const xhr = XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject('Microsoft.XMLHTTP')
// 打开主动请求数据
console.log(xhr.readyState); // 0
xhr.open('GET', url, false)
console.log(xhr.readyState); // 1 HTTP 请求通道打开
xhr.onreadystatechange = function () {
console.log(xhr.readyState); // 4 表示完成所有数据的传输
if (xhr.readyState !== 4) reuturn
if (xhr.status === 200 || xhr.status === 304) {
resolve(xhr.responseText) // 4
} else {
reject(xhr.responseText)
}
}
xhr.send()
console.log(xhr.readyState);
})
}
1. 异步请求概述
AJAX
允许我们通过JavaScript向服务器发送请求并在不刷新整个页面的情况下获取或发送数据。这对于实现更流畅、动态的用户体验至关重要。
2. XMLHttpRequest对象
在JavaScript中,我们使用XMLHttpRequest
对象来创建和发送AJAX请求。因为ie
低版本不支持XMLHttpRequest
,所以为了考虑兼容性,我们通过条件语句选择使用XMLHttpRequest
或ActiveXObject
。
js
const xhr = window.XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject('Microsoft.XMLHTTP');
封装为Promise
为了更好地处理异步操作,我们使用ES6中引入的Promise
对象。因为其提供了一种更清晰的异步编程模式。
js
function getDataByAjax(url) {
return new Promise((resolve, reject) => {
const xhr = window.XMLHttpRequest
? new XMLHttpRequest()
: new ActiveXObject('Microsoft.XMLHTTP');
xhr.open('GET', url, true);
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) return;
if (xhr.status === 200 || xhr.status === 304) {
resolve(xhr.responseText);
} else {
reject(xhr.responseText);
}
};
xhr.send();
});
}
解释:
-
return new Promise((resolve, reject) => { ... })
:getDataByAjax
函数返回一个Promise
对象,该Promise
在异步操作完成时会调用resolve
或reject
,需要注意的是Promise
这个对象本身在事件循环机制中并不会被当作异步任务,而是以同步任务进行执行,当实例化Promise
这个对象时,引擎会立即执行传给它的执行器(executor)
,它就相当于是可以存放异步任务的一个容器,所以我们会将发送请求
-获取响应
放在这个容器里面。 -
const xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
: 创建XMLHttpRequest
对象,以便进行AJAX
请求。通过这种方式实现了对不同浏览器的兼容性
处理。 -
xhr.open('GET', url, true);
: 配置AJAX请求
,使用GET
方法,指定请求的URL
,并设置为异步执行。这时候如果我们打印xhr.readyState
,结果会是1
,表示HTTP
请求通道已经打开。 -
xhr.onreadystatechange = function () { ... }
: 监听xhr
对象的onreadystatechange
事件,当请求状态发生变化时触发。这时候我们再打印xhr.readyState
,结果会是4
,表示完成所有数据的传输。 -
if (xhr.readyState !== 4) return;
: 在onreadystatechange
事件中,首先检查请求状态是否为4
,表示请求完成。 -
if (xhr.status === 200 || xhr.status === 304) { ... } else { ... }
: 根据响应状态码判断请求的成功与失败。如果状态码为200
或304
,表示成功
,调用resolve
并传递响应文本;否则,调用reject
并传递响应文本。 -
xhr.send();
: 最后完成上述步骤,发送AJAX请求。
我们手写的AJAX函数到这里就完成了,这段函数通过使用Promise
,使得该函数在其他地方调用时,也可以使用.then()
和.catch()
来处理AJAX等异步操作的成功和失败情况。
调用手写的AJAX函数
在上面我们已经完成手写AJAX的函数了,接下来让我们检验一下其是否真的可以拿到我们指定的URL中的数据呢?
完整代码
js
// 使用立即执行函数表达式调用异步函数
(async function () {
try {
// 调用异步函数并获取返回的Promise对象
const p = getDataByAjax('https://api.github.com/users/sAnL1ng/repos');
// 输出信息
console.log(p); // Promise 处于 pending 状态
// 使用 await 等待异步操作完成
const data = await p;
// 异步操作完成后的处理
console.log(p); // Promise 从 pending 到 fulfilled 状态
console.log(JSON.parse(data));
} catch (err) {
console.error(err); // 捕获可能的错误
}
})();
然后我们在谷歌浏览器的控制台中运行上述代码就拿到我们想要的数据结果啦(这里请求的数据是博主GitHub中的仓库内容):
代码解析
-
定义异步函数: 首先我们使用
async function
关键字定义了一个异步函数getDataByAjax
,它返回一个Promise对象,用于处理AJAX请求。 -
Promise状态的观察: 在第一个
console.log(p);
处,输出了Promise对象p
的状态,此时处于pending
状态,因为异步操作还没有完成。 -
使用 await 等待异步操作完成: 在第二个
console.log(p);
处,输出了Promise对象p
的状态,此时p
的状态已经从pending
变为fulfilled
,因为前面的await p
等待了p
的异步操作完成。 -
捕获可能的错误: 最后我们使用
try...catch
块捕获可能的错误,确保对异步操作中的异常情况进行处理。
总结
到这里,我们就完成了今天的全部内容啦~总的来说,手写
AJAX
首先我们将整个函数封装成一个Promise
对象,然后使用XMLHttpRequest
对象来创建和发送AJAX
请求,最后根据响应状态码
判断请求的成功与失败。
在当下的前端环境中不管是工作还是面试,AJAX
都是一个十分重要的知识点,对此不太熟悉的小伙伴可以先看我上一篇介绍AJAX三种方法的基础篇,了解完后再来学习如何手写AJAX深入了解AJAX,希望本文对大家有所帮助,感谢阅读,我是散陵我们下篇文章再见!
结语
那么到了这里我们今天的文章就结束啦~
创作不易,如果感觉这个文章对你有帮助的话,点个赞吧♥
更多内容 :如何开启异步通信的新境界?搞懂AJAX中的这三招