ajax_fetch_lifecycle
Fetch 请求生命周期与错误处理
Section titled “Fetch 请求生命周期与错误处理”理解 Promises
Section titled “理解 Promises”fetch API 基于 Promises 构建。Promise 代表异步操作的最终结果。它可以处于以下三种状态之一:
- Pending (待定): 初始状态,既未成功也未失败。
- Fulfilled (已成功): 操作成功完成。Promise 有一个结果值。
- Rejected (已失败): 操作失败。Promise 有一个原因(一个错误)。
您可以使用 .then() 处理成功情况,使用 .catch() 处理失败情况,以及可选的 .finally() 处理无论成功或失败都会运行的代码,以此与 Promise 交互。
`fetch('/api/data')` `.then(response => { // Fulfilled: 网络请求成功 (即使是 404 错误!)` `console.log('Fetch completed, status:', response.status);` `if (!response.ok) { throw new Error('Bad response'); }` `return response.json(); // 返回一个新的 promise` `})` `.then(data => { // Fulfilled: JSON 解析成功` `console.log('Data:', data);` `})` `.catch(error => { // Rejected: 网络错误 或 在 .then() 中抛出的错误` `console.error('Something went wrong:', error);` `})` `.finally(() => { // 可选: 在成功或失败后运行` `console.log('Fetch attempt finished.');` `});`使用 Async/Await
Section titled “使用 Async/Await”async 和 await 为 Promise 提供了语法糖,使得异步代码看起来和行为更像同步代码,许多人觉得这更容易阅读和编写。
async function:声明一个隐式返回 Promise 的函数。允许在其中使用await。await:暂停async函数的执行,直到等待的 Promise 完成(成功或失败)。如果成功,则返回解析的值。如果失败,则抛出失败原因(错误)。
使用 async/await 进行错误处理通常使用标准的 try…catch…finally 块。
async function fetchDataWithAsyncAwait(url) { console.log('Starting fetch...'); // 开始 Fetch... let data = null; try { // Await 暂停执行,直到 fetch promise 完成 const response = await fetch(url); console.log('Response received, checking status...'); // 收到响应,正在检查状态...
// 检查 HTTP 状态 (fetch promise 会成功,即使是 4xx/5xx 错误) if (!response.ok) { // 抛出一个错误,将被 catch 块捕获 throw new Error(`HTTP Error: ${response.status} ${response.statusText}`); }
console.log('Response OK, parsing JSON...'); // 响应正常,正在解析 JSON... // Await 暂停执行,直到 response.json() promise 完成 data = await response.json(); console.log('Data parsed successfully:', data); // 数据解析成功 // 在这里使用数据 document.getElementById('output').textContent = JSON.stringify(data, null, 2);
} catch (error) { // 捕获网络错误 (fetch rejected) 或手动抛出的错误 (例如 !response.ok) console.error('Error during fetch operation:', error); // Fetch 操作期间发生错误 document.getElementById('output').textContent = `Error: ${error.message}`; } finally { // 无论 try 块成功还是失败都会运行 console.log('Fetch attempt finished.'); // Fetch 尝试完成。 } return data; // 异步函数返回一个 promise,它将解析为该值 (如果出错则为 undefined)}
// 示例用法// fetchDataWithAsyncAwait('https://jsonplaceholder.typicode.com/todos/1');// fetchDataWithAsyncAwait('https://jsonplaceholder.typicode.com/invalid-url'); // 错误示例处理不同类型的错误
Section titled “处理不同类型的错误”发出请求时,错误可能发生在不同阶段:
- 网络错误 (Network Errors):由于网络问题(例如,DNS 查找失败、无网络连接、在请求发送之前检测到 CORS 违规)导致请求无法完成。
fetch()promise 本身将失败 (reject)。 - HTTP 错误 (HTTP Errors):服务器已响应,但状态码表示错误(例如,404 Not Found、500 Internal Server Error、401 Unauthorized)。
fetch()promise 将成功 (fulfill),但response.ok将为false。您需要检查response.ok或response.status并明确处理此情况(通常通过抛出错误)。 - 解析错误 (Parsing Errors):服务器以状态 200 OK 响应,但响应体内容不是预期的格式(例如,尝试使用
response.json()将 HTML 解析为 JSON)。读取响应体的方法(.json()、.text()等)的 promise 将失败 (reject)。 - 应用级错误 (Application Errors):服务器以状态 200 OK 和有效格式(例如,JSON)响应,但数据指示了一个逻辑错误(例如,
{ “success”: false, “error”: “Invalid user ID” })。您需要检查响应数据本身来检测这些错误。
健壮的错误处理涉及预测这些不同的失败模式。
async function robustFetch(url) { try { const response = await fetch(url);
// 处理 HTTP 错误 (服务器已响应,但状态为错误) if (!response.ok) { let errorData; try { // 尝试从错误响应体获取更多详情 (通常是 JSON) errorData = await response.json(); } catch (parseError) { // 如果解析失败,使用状态文本 errorData = { message: response.statusText }; } throw new Error(`HTTP ${response.status}: ${errorData.message || 'Unknown server error'}`); // 未知的服务器错误 }
// 处理解析错误 let data; try { data = await response.json(); } catch (parseError) { throw new Error(`Failed to parse JSON response: ${parseError.message}`); // 解析 JSON 响应失败 }
// 处理应用级错误 (可选,取决于 API 设计) // if (data.success === false) { // 如果数据指示逻辑失败 // throw new Error(`API Error: ${data.error}`); // API 错误 // }
console.log('Success:', data); // 成功 return data;
} catch (error) { // 捕获网络错误 (fetch rejected) 和上面抛出的错误 console.error(`Fetch failed: ${error.message}`); // Fetch 失败 // 潜在地更新 UI 显示错误 // throw error; // 如果需要更高层级处理则重新抛出 }}
// robustFetch('/api/resource');// robustFetch('/api/not-found'); // 404 示例// robustFetch('/api/invalid-json'); // 解析错误示例关于 Promises 的更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
关于 async/await 的更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function