AJAX 事件
处理异步操作:Promises 和 Async/Await
Section titled “处理异步操作:Promises 和 Async/Await”现代 JavaScript 严重依赖 Promise 和 async/await 语法来管理网络请求(Fetch API)、定时器等异步操作。这提供了一种比基于旧式回调的模式更清晰、更易于管理的替代方案。
理解 Promises
Section titled “理解 Promises”Promise 是一个对象,代表异步操作最终完成(或失败)及其结果值。
Promise 可以处于以下三种状态之一:
- **Pending(待定):**初始状态,既未成功也未失败。
- **Fulfilled(已成功):**操作成功完成,Promise 具有结果值。
- **Rejected(已失败):**操作失败,Promise 具有失败的原因(一个错误)。
Fetch API 返回 Promise。你可以使用 .then()、.catch() 和 .finally() 方法与它们进行交互。
使用 .then() 和 .catch()
Section titled “使用 .then() 和 .catch()”-
.then(onFulfilled, onRejected):为成功和失败状态附加回调函数。通常,你使用.then(onFulfilled)处理成功情况,然后链式调用.catch(onRejected)处理错误。 -
.catch(onRejected):仅为失败状态附加回调函数。捕获来自前一个 Promise 或链中任何.then()回调的错误。 -
.finally(onFinally):附加一个回调函数,该函数无论 Promise 成功还是失败都会执行(例如,用于清理工作)。
使用 Fetch 和 Promises 的示例:console.log('Starting fetch...');
fetch('https://api.example.com/data') .then(response => { console.log('Received response object.'); if (!response.ok) { // If status code is not OK, create an error to be caught by .catch() throw new Error(`Network response was not ok: ${response.status}`); } return response.json(); // Returns another Promise }) .then(data => { console.log('Data parsed successfully:', data); // Update UI with data document.getElementById('content').innerText = JSON.stringify(data, null, 2); }) .catch(error => { console.error('Fetch operation failed:', error); // Display error message document.getElementById('content').innerText = `Error: ${error.message}`; }) .finally(() => { console.log('Fetch attempt finished (either success or failure).'); // Hide loading indicator, etc. });
console.log('Fetch initiated, but code continues executing...');注意 .then() 处理器是如何链式调用的。每个 .then() 都会接收前一个 Promise 或回调的结果。
使用 Async/Await 进行简化
Section titled “使用 Async/Await 进行简化”async/await 是基于 Promises 构建的语法糖,它允许你编写看起来和行为上更像同步代码的异步代码,使其更容易阅读和维护。
-
async function:使用async关键字声明一个函数意味着它将自动返回一个 Promise。该 Promise 的 resolved 值将是该函数返回的任何值。 -
await:await运算符只能在async function内部使用。它会暂停async function的执行,直到它等待的 Promise 状态确定(成功或失败)。如果成功,它返回 resolved 值。如果失败,它抛出错误。
使用 `async/await` 重写的上一个示例:async function fetchData() { const contentElement = document.getElementById('content'); console.log('Starting fetch...'); try { const response = await fetch('https://api.example.com/data'); console.log('Received response object.');
if (!response.ok) { throw new Error(`Network response was not ok: ${response.status}`); }
const data = await response.json(); // Wait for JSON parsing console.log('Data parsed successfully:', data);
// Update UI with data contentElement.innerText = JSON.stringify(data, null, 2);
} catch (error) { // Errors from fetch() or thrown manually are caught here console.error('Fetch operation failed:', error); contentElement.innerText = `Error: ${error.message}`;
} finally { console.log('Fetch attempt finished (either success or failure).'); // Hide loading indicator, etc. }}
console.log('Calling fetchData...');fetchData(); // Call the async functionconsole.log('fetchData called, but code continues executing...');async/await 的主要优点:
- 可读性:看起来比嵌套的
.then()链清晰得多。 - 错误处理:可以使用标准的
try...catch块来处理 awaited Promises 中的错误。 - 调试:在调试器中单步执行
await调用通常更直观。
遗留技术:XMLHttpRequest 和 onreadystatechange
Section titled “遗留技术:XMLHttpRequest 和 onreadystatechange”在 Fetch 和 Promises 出现之前,XMLHttpRequest (XHR) 是发起异步请求的主要方式。它采用基于事件的方法。
onreadystatechange 事件处理程序在请求生命周期中会被多次调用,指示 readyState 属性的变化。
| 属性 | 描述 |
|---|---|
onreadystatechange | 存储一个函数,该函数在 readyState 属性改变时被调用。 |
readyState | 保存 XMLHttpRequest 的状态。从 0 变到 4:0: 请求未初始化 1: 服务器连接已建立 2: 请求已接收 3: 正在处理请求 4: 请求已完成且响应已就绪 |
status | 保存 HTTP 状态码(例如,200 表示 “OK”,404 表示 “Not Found”),该值在请求完成后(即 readyState 为 4 时)可用。 |
典型的 XHR 模式是在 onreadystatechange 处理程序内部检查 readyState 是否为 4 且 status 是否为 200:
// --- LEGACY EXAMPLE --- Not recommended for new code ---const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() { // Check if the request is complete and was successful if (xhr.readyState === 4) { if (xhr.status === 200) { // Success! console.log('XHR Success:', xhr.responseText); document.getElementById('myDiv').innerHTML = xhr.responseText; } else { // Error (e.g., 404, 500) console.error('XHR Error:', xhr.status, xhr.statusText); document.getElementById('myDiv').innerHTML = 'Error loading data.'; } }};
// Configure the request (GET request to 'data.txt')xhr.open('GET', 'data.txt', true); // true makes it asynchronous
// Optional: Handle network errorsxhr.onerror = function() { console.error('XHR Network Error occurred');};
// Send the requestxhr.send();虽然你可能在旧的代码库中遇到 XHR,但由于其更简洁的语法和与现代 JavaScript 特性的更好集成,Fetch API 结合 Promises 或 async/await 是新开发的标准。