|
| 1 | +# 使用 promise 手写一个 Ajax 请求 |
| 2 | + |
| 3 | +> 本篇文章使用ChatGPT辅助编写 |
| 4 | +
|
| 5 | +## 阅读本人您将收获 |
| 6 | +* 手写 `Ajax` 请求 |
| 7 | +* 使用 `Promise` 手写 `Ajax` 请求 |
| 8 | +* 两种方式优缺点 |
| 9 | + |
| 10 | +## 一个最基础的 `Ajax` 请求 |
| 11 | + |
| 12 | +``` |
| 13 | +// 创建一个 XMLHttpRequest 对象 |
| 14 | +var xhr = new XMLHttpRequest(); |
| 15 | +
|
| 16 | +// 配置请求 |
| 17 | +xhr.open("GET", "https://jsonplaceholder.typicode.com/posts/1", true); |
| 18 | +
|
| 19 | +// 设置请求完成时的回调函数 |
| 20 | +xhr.onreadystatechange = function () { |
| 21 | + // 检查请求是否完成 |
| 22 | + if (xhr.readyState === 4) { |
| 23 | + // 检查 HTTP 响应状态 |
| 24 | + if (xhr.status === 200) { |
| 25 | + // 请求成功,处理响应数据 |
| 26 | + console.log("成功响应:", xhr.responseText); |
| 27 | + } else { |
| 28 | + // 请求失败,处理错误 |
| 29 | + console.error("请求失败,状态码:", xhr.status); |
| 30 | + } |
| 31 | + } |
| 32 | +}; |
| 33 | +
|
| 34 | +// 设置网络错误的回调函数 |
| 35 | +xhr.onerror = function () { |
| 36 | + console.error("网络错误"); |
| 37 | +}; |
| 38 | +
|
| 39 | +// 发送请求 |
| 40 | +xhr.send(); |
| 41 | +``` |
| 42 | + |
| 43 | +## 使用 `Promise` 手写 `Ajax` 请求 |
| 44 | + |
| 45 | +* 下面是一个使用 Promise 手写的简单 AJAX 请求的示例 |
| 46 | + |
| 47 | +``` |
| 48 | +// 步骤 1: 创建一个函数,该函数返回一个 Promise 对象 |
| 49 | +function makeAjaxRequest(url, method) { |
| 50 | + return new Promise((resolve, reject) => { |
| 51 | + // 步骤 2: 创建一个 XMLHttpRequest 对象 |
| 52 | + const xhr = new XMLHttpRequest(); |
| 53 | +
|
| 54 | + // 步骤 3: 配置请求 |
| 55 | + xhr.open(method, url, true); |
| 56 | +
|
| 57 | + // 步骤 4: 设置请求完成时的回调函数 |
| 58 | + xhr.onload = function () { |
| 59 | + // 步骤 5: 检查 HTTP 响应状态 |
| 60 | + if (xhr.status === 200) { |
| 61 | + // 请求成功,调用 resolve 并传递响应数据 |
| 62 | + resolve(xhr.responseText); |
| 63 | + } else { |
| 64 | + // 请求失败,调用 reject 并传递错误信息 |
| 65 | + reject(xhr.statusText); |
| 66 | + } |
| 67 | + }; |
| 68 | +
|
| 69 | + // 步骤 6: 设置网络错误的回调函数 |
| 70 | + xhr.onerror = function () { |
| 71 | + // 网络错误,调用 reject 并传递错误信息 |
| 72 | + reject("网络错误"); |
| 73 | + }; |
| 74 | +
|
| 75 | + // 步骤 7: 发送请求 |
| 76 | + xhr.send(); |
| 77 | + }); |
| 78 | +} |
| 79 | +
|
| 80 | +// 步骤 8: 使用 Promise 来进行 AJAX 请求 |
| 81 | +makeAjaxRequest("https://jsonplaceholder.typicode.com/posts/1", "GET") |
| 82 | + .then((response) => { |
| 83 | + console.log("成功响应:", response); |
| 84 | + }) |
| 85 | + .catch((error) => { |
| 86 | + console.error("错误:", error); |
| 87 | + }); |
| 88 | +``` |
| 89 | + |
| 90 | +**代码分解:** |
| 91 | + |
| 92 | +1. 创建一个名为 `makeAjaxRequest` 的函数,它接受 `url` 和 `method` 作为参数,并返回一个 Promise 对象。 |
| 93 | + |
| 94 | +2. 在 Promise 构造函数中,创建一个 XMLHttpRequest 对象 `xhr`,用于发起 AJAX 请求。 |
| 95 | + |
| 96 | +3. 使用 `xhr.open()` 配置请求,设置请求方法和 URL。 |
| 97 | + |
| 98 | +4. 设置 `xhr.onload` 回调函数,当请求完成时触发。 |
| 99 | + |
| 100 | +5. 在 `xhr.onload` 回调函数中,检查 HTTP 响应状态。如果状态码为 200,表示请求成功,调用 `resolve` 并传递响应数据 `xhr.responseText`。 |
| 101 | + |
| 102 | +6. 设置 `xhr.onerror` 回调函数,处理网络错误情况。 |
| 103 | + |
| 104 | +7. 在 `xhr.onerror` 回调函数中,调用 `reject` 并传递错误信息 "网络错误"。 |
| 105 | + |
| 106 | +8. 使用 `makeAjaxRequest` 函数发起 AJAX 请求,并通过 `.then()` 处理成功响应和 `.catch()` 处理错误。如果请求成功,将输出响应数据,否则将输出错误信息。 |
| 107 | + |
| 108 | +## 优缺点 |
| 109 | +基础的 `AJAX` 请求和使用 `Promise` 的 `AJAX` 请求各有优点和缺点。下面是它们的主要区别: |
| 110 | + |
| 111 | +**基础的 AJAX 请求:** |
| 112 | + |
| 113 | +**优点:** |
| 114 | + |
| 115 | +1. 相对简单:传统的 `AJAX` 请求使用回调函数,对于简单的异步操作来说,代码相对较简单。 |
| 116 | + |
| 117 | +2. 兼容性好:基础的 `AJAX` 请求在各种浏览器中都有很好的兼容性,不需要额外的库或工具。 |
| 118 | + |
| 119 | +**缺点:** |
| 120 | + |
| 121 | +1. 回调地狱(`Callback Hell`):当处理多个嵌套的异步操作时,容易导致回调函数的嵌套,使代码难以理解和维护。 |
| 122 | + |
| 123 | +2. 错误处理不方便:错误处理通常需要在每个回调函数中处理,导致错误处理逻辑分散和混乱。 |
| 124 | + |
| 125 | +**使用 Promise 的 AJAX 请求:** |
| 126 | + |
| 127 | +**优点:** |
| 128 | + |
| 129 | +1. 更清晰的代码结构:`Promise` 可以使用链式调用,使代码更具可读性,避免了回调地狱问题。 |
| 130 | + |
| 131 | +2. 统一的错误处理:`Promise` 提供了 `.catch()` 方法,可以集中处理所有错误,使错误处理更加方便和一致。 |
| 132 | + |
| 133 | +3. 支持异步/等待(`async/await`):与 `Promise` 结合使用的 `async/await` 语法可以进一步提高代码的可读性,使异步代码看起来更像同步代码。 |
| 134 | + |
| 135 | +**缺点:** |
| 136 | + |
| 137 | +1. 学习曲线:对于初学者来说,Promise 可能需要一些时间来理解和掌握,尤其是对于复杂的异步场景。 |
| 138 | + |
| 139 | +2. 兼容性:`Promise` 不支持一些古老的浏览器,但可以通过使用 `polyfill` 或转译工具来解决。 |
0 commit comments