当前位置: 首页 > wzjs >正文

wordpress如何更改页面链接地址湖南靠谱关键词优化

wordpress如何更改页面链接地址,湖南靠谱关键词优化,语言教学网站建设课程总结,用dw做网站的过程Ajax 通俗易懂学习手册 目录 Ajax 基础概念XMLHttpRequest 详解Fetch API (现代方式)处理不同数据格式错误处理和状态码Ajax 高级技巧实战项目案例最佳实践 Ajax 基础概念 什么是 Ajax? Ajax Asynchronous JavaScript And XML 通俗解释: Ajax 就像…

Ajax 通俗易懂学习手册

目录

  1. Ajax 基础概念
  2. XMLHttpRequest 详解
  3. Fetch API (现代方式)
  4. 处理不同数据格式
  5. 错误处理和状态码
  6. Ajax 高级技巧
  7. 实战项目案例
  8. 最佳实践

Ajax 基础概念

什么是 Ajax?

Ajax = Asynchronous JavaScript And XML

通俗解释: Ajax 就像"外卖小哥",你在网页上点了个按钮(下单),Ajax 悄悄跑到服务器那里取数据(送餐),拿回来后更新页面(送到你手上),整个过程你不用刷新页面!

Ajax 的优势

  • 无需刷新页面 - 用户体验更好
  • 节省带宽 - 只传输需要的数据
  • 提高性能 - 减少服务器负担
  • 实时交互 - 即时获取最新数据

Ajax 能做什么?

// 常见应用场景
- 搜索建议(输入时实时显示)
- 无限滚动(微博、朋友圈)
- 表单验证(检查用户名是否存在)
- 购物车更新(不刷新页面添加商品)
- 聊天应用(实时收发消息)
- 天气查询(获取实时天气)

XMLHttpRequest 详解

基础用法 - 一步步学会

// 第1步:创建 XMLHttpRequest 对象
const xhr = new XMLHttpRequest();// 第2步:配置请求
xhr.open('GET', 'https://api.example.com/users', true);
// 参数说明:
// - 'GET': 请求方法
// - URL: 请求地址
// - true: 是否异步(几乎总是true)// 第3步:设置响应处理
xhr.onreadystatechange = function() {if (xhr.readyState === 4 && xhr.status === 200) {console.log('请求成功!');const data = JSON.parse(xhr.responseText);console.log(data);}
};// 第4步:发送请求
xhr.send();

理解 readyState(请求状态)

// readyState 的5种状态
0: UNSENT - 请求未初始化
1: OPENED - 连接已建立
2: HEADERS_RECEIVED - 请求已接收
3: LOADING - 请求处理中
4: DONE - 请求已完成// 实际使用中的状态检查
xhr.onreadystatechange = function() {console.log('当前状态:', xhr.readyState);if (xhr.readyState === 4) {if (xhr.status === 200) {console.log('成功!', xhr.responseText);} else {console.log('出错了,状态码:', xhr.status);}}
};

GET 请求完整示例

function getData(url, callback) {const xhr = new XMLHttpRequest();xhr.open('GET', url, true);// 设置请求头(可选)xhr.setRequestHeader('Content-Type', 'application/json');xhr.onreadystatechange = function() {if (xhr.readyState === 4) {if (xhr.status === 200) {const data = JSON.parse(xhr.responseText);callback(null, data); // 成功} else {callback(new Error(`请求失败: ${xhr.status}`)); // 失败}}};xhr.send();
}// 使用示例
getData('https://jsonplaceholder.typicode.com/posts', (error, data) => {if (error) {console.error('出错了:', error.message);} else {console.log('获取到的数据:', data);}
});

POST 请求 - 发送数据

function postData(url, data, callback) {const xhr = new XMLHttpRequest();xhr.open('POST', url, true);// POST 请求必须设置这个头部xhr.setRequestHeader('Content-Type', 'application/json');xhr.onreadystatechange = function() {if (xhr.readyState === 4) {if (xhr.status === 200 || xhr.status === 201) {const response = JSON.parse(xhr.responseText);callback(null, response);} else {callback(new Error(`请求失败: ${xhr.status}`));}}};// 发送 JSON 数据xhr.send(JSON.stringify(data));
}// 使用示例:创建新用户
const newUser = {name: '小明',email: 'xiaoming@example.com',age: 25
};postData('https://jsonplaceholder.typicode.com/users', newUser, (error, response) => {if (error) {console.error('创建用户失败:', error.message);} else {console.log('创建成功:', response);}
});

封装成通用函数

function ajax(options) {// 默认设置const defaults = {method: 'GET',url: '',data: null,headers: {},timeout: 5000,success: function() {},error: function() {}};// 合并配置const config = { ...defaults, ...options };const xhr = new XMLHttpRequest();// 设置超时xhr.timeout = config.timeout;xhr.open(config.method, config.url, true);// 设置请求头for (let key in config.headers) {xhr.setRequestHeader(key, config.headers[key]);}// 如果是 POST 请求且有数据,设置默认 Content-Typeif (config.method === 'POST' && config.data && !config.headers['Content-Type']) {xhr.setRequestHeader('Content-Type', 'application/json');}xhr.onreadystatechange = function() {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) {let response = xhr.responseText;try {response = JSON.parse(response);} catch (e) {// 如果不是 JSON,保持原样}config.success(response);} else {config.error(new Error(`HTTP ${xhr.status}: ${xhr.statusText}`));}}};xhr.ontimeout = function() {config.error(new Error('请求超时'));};// 发送数据let sendData = config.data;if (sendData && typeof sendData === 'object') {sendData = JSON.stringify(sendData);}xhr.send(sendData);
}// 使用示例
ajax({method: 'GET',url: 'https://jsonplaceholder.typicode.com/posts/1',success: function(data) {console.log('获取成功:', data);},error: function(error) {console.error('请求失败:', error.message);}
});

Fetch API (现代方式)

为什么用 Fetch?

Fetch 是现代浏览器提供的新 API,比 XMLHttpRequest 更简洁、更强大!

优势:

  • ✅ 基于 Promise,支持 async/await
  • ✅ 语法更简洁
  • ✅ 更好的错误处理
  • ✅ 支持流式数据

基础 GET 请求

// 基础用法
fetch('https://jsonplaceholder.typicode.com/posts/1').then(response => response.json()).then(data => console.log(data)).catch(error => console.error('出错了:', error));// 使用 async/await(推荐)
async function fetchData() {try {const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');const data = await response.json();console.log(data);} catch (error) {console.error('出错了:', error);}
}fetchData();

POST 请求

async function createPost(postData) {try {const response = await fetch('https://jsonplaceholder.typicode.com/posts', {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify(postData)});if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}const result = await response.json();console.log('创建成功:', result);return result;} catch (error) {console.error('创建失败:', error);}
}// 使用示例
createPost({title: '我的第一篇博客',body: '这是内容...',userId: 1
});

常用的 HTTP 方法

class ApiService {constructor(baseURL) {this.baseURL = baseURL;}// GET - 获取数据async get(endpoint) {const response = await fetch(`${this.baseURL}${endpoint}`);return this.handleResponse(response);}// POST - 创建数据async post(endpoint, data) {const response = await fetch(`${this.baseURL}${endpoint}`, {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(data)});return this.handleResponse(response);}// PUT - 更新数据async put(endpoint, data) {const response = await fetch(`${this.baseURL}${endpoint}`, {method: 'PUT',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(data)});return this.handleResponse(response);}// DELETE - 删除数据async delete(endpoint) {const response = await fetch(`${this.baseURL}${endpoint}`, {method: 'DELETE'});return this.handleResponse(response);}// 统一处理响应async handleResponse(response) {if (!response.ok) {throw new Error(`HTTP ${response.status}: ${response.statusText}`);}// 如果没有内容,返回 nullif (response.status === 204) {return null;}return await response.json();}
}// 使用示例
const api = new ApiService('https://jsonplaceholder.typicode.com');async function example() {try {// 获取所有文章const posts = await api.get('/posts');console.log('所有文章:', posts);// 创建新文章const newPost = await api.post('/posts', {title: '新文章',body: '文章内容',userId: 1});console.log('新文章:', newPost);// 更新文章const updatedPost = await api.put('/posts/1', {id: 1,title: '更新的标题',body: '更新的内容',userId: 1});console.log('更新后:', updatedPost);// 删除文章await api.delete('/posts/1');console.log('删除成功');} catch (error) {console.error('操作失败:', error.message);}
}

处理不同数据格式

JSON 数据(最常用)

// 发送 JSON
async function sendJSON(data) {const response = await fetch('/api/users', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify(data)});return await response.json();
}// 接收 JSON
async function receiveJSON() {const response = await fetch('/api/users');const data = await response.json();return data;
}

表单数据

// 发送表单数据
async function sendFormData(formElement) {const formData = new FormData(formElement);const response = await fetch('/api/upload', {method: 'POST',body: formData // 注意:不要设置 Content-Type,让浏览器自动设置});return await response.json();
}// 手动创建表单数据
async function sendCustomFormData() {const formData = new FormData();formData.append('name', '小明');formData.append('age', '25');formData.append('avatar', fileInput.files[0]); // 文件const response = await fetch('/api/profile', {method: 'POST',body: formData});return await response.json();
}

文件上传

// 单文件上传
async function uploadFile(file) {const formData = new FormData();formData.append('file', file);try {const response = await fetch('/api/upload', {method: 'POST',body: formData});if (!response.ok) {throw new Error('上传失败');}const result = await response.json();console.log('上传成功:', result);return result;} catch (error) {console.error('上传出错:', error);}
}// 多文件上传
async function uploadMultipleFiles(files) {const formData = new FormData();for (let i = 0; i < files.length; i++) {formData.append('files', files[i]);}const response = await fetch('/api/upload-multiple', {method: 'POST',body: formData});return await response.json();
}// 带进度的文件上传(使用 XMLHttpRequest)
function uploadWithProgress(file, onProgress) {return new Promise((resolve, reject) => {const formData = new FormData();formData.append('file', file);const xhr = new XMLHttpRequest();// 上传进度xhr.upload.addEventListener('progress', (e) => {if (e.lengthComputable) {const percentComplete = (e.loaded / e.total) * 100;onProgress(percentComplete);}});xhr.addEventListener('load', () => {if (xhr.status === 200) {resolve(JSON.parse(xhr.responseText));} else {reject(new Error('上传失败'));}});xhr.addEventListener('error', () => {reject(new Error('网络错误'));});xhr.open('POST', '/api/upload');xhr.send(formData);});
}// 使用示例
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', async (e) => {const file = e.target.files[0];if (file) {try {const result = await uploadWithProgress(file, (progress) => {console.log(`上传进度:${progress.toFixed(1)}%`);});console.log('上传完成:', result);} catch (error) {console.error('上传失败:', error);}}
});

处理其他格式

// 获取纯文本
async function getText() {const response = await fetch('/api/readme.txt');const text = await response.text();return text;
}// 获取二进制数据
async function getBinaryData() {const response = await fetch('/api/image.jpg');const blob = await response.blob();return blob;
}// 获取数组缓冲区
async function getArrayBuffer() {const response = await fetch('/api/data.bin');const buffer = await response.arrayBuffer();return buffer;
}

错误处理和状态码

HTTP 状态码详解

// 常见状态码及其含义
const statusCodes = {200: '成功',201: '创建成功',204: '删除成功(无内容)',400: '请求参数错误',401: '未授权',403: '禁止访问',404: '资源不存在',500: '服务器内部错误',502: '网关错误',503: '服务不可用'
};function getStatusMessage(status) {return statusCodes[status] || '未知错误';
}

完善的错误处理

class ApiError extends Error {constructor(status, message, data = null) {super(message);this.name = 'ApiError';this.status = status;this.data = data;}
}async function safeFetch(url, options = {}) {try {const response = await fetch(url, options);// 检查响应状态if (!response.ok) {let errorData = null;try {errorData = await response.json();} catch (e) {// 如果响应不是 JSON,忽略}throw new ApiError(response.status,errorData?.message || `HTTP ${response.status}: ${response.statusText}`,errorData);}// 根据 Content-Type 自动解析const contentType = response.headers.get('content-type');if (contentType && contentType.includes('application/json')) {return await response.json();} else if (contentType && contentType.includes('text/')) {return await response.text();} else {return await response.blob();}} catch (error) {if (error instanceof ApiError) {throw error;}// 网络错误if (error.name === 'TypeError') {throw new ApiError(0, '网络连接失败,请检查网络设置');}// 其他错误throw new ApiError(0, error.message);}
}// 使用示例
async function handleApiCall() {try {const data = await safeFetch('/api/users/123');console.log('获取成功:', data);} catch (error) {if (error instanceof ApiError) {switch (error.status) {case 401:console.error('请先登录');// 跳转到登录页break;case 403:console.error('权限不足');break;case 404:console.error('用户不存在');break;case 0:console.error('网络错误:', error.message);break;default:console.error('请求失败:', error.message);}} else {console.error('未知错误:', error);}}
}

重试机制

async function fetchWithRetry(url, options = {}, maxRetries = 3) {let lastError;for (let i = 0; i <= maxRetries; i++) {try {const response = await fetch(url, options);// 如果是服务器错误且还有重试次数,继续重试if (response.status >= 500 && i < maxRetries) {throw new Error(`服务器错误 ${response.status}`);}if (!response.ok) {throw new Error(`HTTP ${response.status}`);}return await response.json();} catch (error) {lastError = error;if (i < maxRetries) {console.log(`${i + 1} 次请求失败,${1}秒后重试...`);await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))); // 指数退避}}}throw lastError;
}// 使用示例
async function robustApiCall() {try {const data = await fetchWithRetry('/api/unstable-endpoint');console.log('最终成功:', data);} catch (error) {console.error('重试后仍然失败:', error.message);}
}

Ajax 高级技巧

取消请求

// 使用 AbortController 取消请求
function cancelableRequest(url) {const controller = new AbortController();const promise = fetch(url, {signal: controller.signal}).then(response => response.json());// 返回 promise 和取消函数return {promise,cancel: () => controller.abort()};
}// 使用示例
const { promise, cancel } = cancelableRequest('/api/slow-endpoint');// 5秒后自动取消
setTimeout(() => {cancel();console.log('请求已取消');
}, 5000);promise.then(data => console.log('获取成功:', data)).catch(error => {if (error.name === 'AbortError') {console.log('请求被取消了');} else {console.error('请求失败:', error);}});

请求缓存

class ApiCache {constructor(expireTime = 5 * 60 * 1000) { // 默认5分钟过期this.cache = new Map();this.expireTime = expireTime;}// 生成缓存键getCacheKey(url, options = {}) {return JSON.stringify({ url, ...options });}// 获取缓存get(key) {const item = this.cache.get(key);if (!item) return null;// 检查是否过期if (Date.now() > item.expireAt) {this.cache.delete(key);return null;}return item.data;}// 设置缓存set(key, data) {this.cache.set(key, {data,expireAt: Date.now() + this.expireTime});}// 带缓存的请求async fetch(url, options = {}) {const cacheKey = this.getCacheKey(url, options);// 先查缓存const cached = this.get(cacheKey);if (cached) {console.log('使用缓存数据');return cached;}// 发起请求const response = await fetch(url, options);if (!response.ok) {throw new Error(`HTTP ${response.status}`);}const data = await response.json();// 缓存结果this.set(cacheKey, data);return data;}// 清除缓存clear() {this.cache.clear();}
}// 使用示例
const apiCache = new ApiCache();async function getCachedData() {try {const data = await apiCache.fetch('/api/users');console.log('数据:', data);} catch (error) {console.error('获取失败:', error);}
}// 第一次调用会发起请求
getCachedData();// 第二次调用会使用缓存
setTimeout(() => {getCachedData(); // 使用缓存
}, 1000);

并发控制

class RequestQueue {constructor(maxConcurrent = 3) {this.maxConcurrent = maxConcurrent;this.running = 0;this.queue = [];}async add(requestFn) {return new Promise((resolve, reject) => {this.queue.push({requestFn,resolve,reject});this.process();});}async process() {if (this.running >= this.maxConcurrent || this.queue.length === 0) {return;}this.running++;const { requestFn, resolve, reject } = this.queue.shift();try {const result = await requestFn();resolve(result);} catch (error) {reject(error);} finally {this.running--;this.process(); // 处理下一个请求}}
}// 使用示例
const requestQueue = new RequestQueue(2); // 最多同时2个请求async function batchRequests() {const urls = ['/api/user/1','/api/user/2','/api/user/3','/api/user/4','/api/user/5'];const promises = urls.map(url => requestQueue.add(() => fetch(url).then(r => r.json())));try {const results = await Promise.all(promises);console.log('所有请求完成:', results);} catch (error) {console.error('批量请求失败:', error);}
}batchRequests();

实战项目案例

用户管理系统

class UserManager {constructor() {this.baseURL = '/api/users';this.users = [];this.init();}async init() {await this.loadUsers();this.bindEvents();}// 加载用户列表async loadUsers() {try {const response = await fetch(this.baseURL);this.users = await response.json();this.renderUsers();} catch (error) {this.showError('加载用户失败:' + error.message);}}// 创建用户async createUser(userData) {try {const response = await fetch(this.baseURL, {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(userData)});if (!response.ok) {throw new Error('创建失败');}const newUser = await response.json();this.users.push(newUser);this.renderUsers();this.showSuccess('用户创建成功!');} catch (error) {this.showError('创建用户失败:' + error.message);}}// 更新用户async updateUser(id, userData) {try {const response = await fetch(`${this.baseURL}/${id}`, {method: 'PUT',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(userData)});if (!response.ok) {throw new Error('更新失败');}const updatedUser = await response.json();const index = this.users.findIndex(u => u.id === id);if (index !== -1) {this.users[index] = updatedUser;this.renderUsers();this.showSuccess('用户更新成功!');}} catch (error) {this.showError('更新用户失败:' + error.message);}}// 删除用户async deleteUser(id) {if (!confirm('确定要删除这个用户吗?')) {return;}try {const response = await fetch(`${this.baseURL}/${id}`, {method: 'DELETE'});if (!response.ok) {throw new Error('删除失败');}this.users = this.users.filter(u => u.id !== id);this.renderUsers();this.showSuccess('用户删除成功!');} catch (error) {this.showError('删除用户失败:' + error.message);}}// 渲染用户列表renderUsers() {const container = document.getElementById('userList');container.innerHTML = this.users.map(user => `<div class="user-item" data-id="${user.id}"><h3>${user.name}</h3><p>邮箱:${user.email}</p><p>年龄:${user.age}</p><button onclick="userManager.editUser(${user.id})">编辑</button><button onclick="userManager.deleteUser(${user.id})">删除</button></div>`).join('');}// 绑定事件bindEvents() {// 创建用户表单document.getElementById('createForm').addEventListener('submit', async (e) => {e.preventDefault();const formData = new FormData(e.target);const userData = {name: formData.get('name'),email: formData.get('email'),age: parseInt(formData.get('age'))};await this.createUser(userData);e.target.reset();});}// 编辑用户editUser(id) {const user = this.users.find(u => u.id === id);if (user) {document.getElementById('editName').value = user.name;document.getElementById('editEmail').value = user.email;document.getElementById('editAge').value = user.age;document.getElementById('editModal').style.display = 'block';document.getElementById('editForm').onsubmit = async (e) => {e.preventDefault();const formData = new FormData(e.target);const userData = {name: formData.get('name'),email: formData.get('email'),age: parseInt(formData.get('age'))};await this.updateUser(id, userData);document.getElementById('editModal').style.display = 'none';};}}// 显示成功消息showSuccess(message) {this.showMessage(message, 'success');}// 显示错误消息showError(message) {this.showMessage(message, 'error');}// 显示消息showMessage(message, type) {const messageDiv = document.createElement('div');messageDiv.className = `message ${type}`;messageDiv.textContent = message;document.body.appendChild(messageDiv);setTimeout(() => {messageDiv.remove();}, 3000);}
}// 初始化
const userManager = new UserManager();

搜索建议功能

class SearchSuggestion {constructor(inputId, suggestionsId) {this.input = document.getElementById(inputId);this.suggestionsContainer = document.getElementById(suggestionsId);this.cache = new Map();this.currentRequest = null;this.debounceTimer = null;this.init();}init() {this.input.addEventListener('input', (e) => {this.debounceSearch(e.target.value);});this.input.addEventListener('keydown', (e) => {this.handleKeyboard(e);});// 点击外部关闭建议document.addEventListener('click', (e) => {if (!this.input.contains(e.target) && !this.suggestionsContainer.contains(e.target)) {this.hideSuggestions();}});}// 防抖搜索debounceSearch(query) {clearTimeout(this.debounceTimer);this.debounceTimer = setTimeout(() => {this.search(query);}, 300);}async search(query) {if (!query.trim()) {this.hideSuggestions();return;}// 取消之前的请求if (this.currentRequest) {this.currentRequest.abort();}// 检查缓存if (this.cache.has(query)) {this.showSuggestions(this.cache.get(query));return;}try {const controller = new AbortController();this.currentRequest = controller;const response = await fetch(`/api/search/suggestions?q=${encodeURIComponent(query)}`, {signal: controller.signal});if (!response.ok) {throw new Error('搜索失败');}const suggestions = await response.json();// 缓存结果this.cache.set(query, suggestions);this.showSuggestions(suggestions);} catch (error) {if (error.name !== 'AbortError') {console.error('搜索出错:', error);}} finally {this.currentRequest = null;}}showSuggestions(suggestions) {if (suggestions.length === 0) {this.hideSuggestions();return;}const html = suggestions.map((item, index) => `<div class="suggestion-item" data-index="${index}" onclick="searchSuggestion.selectSuggestion('${item.text}')"><span class="suggestion-text">${this.highlightQuery(item.text)}</span><span class="suggestion-count">${item.count} 个结果</span></div>`).join('');this.suggestionsContainer.innerHTML = html;this.suggestionsContainer.style.display = 'block';}hideSuggestions() {this.suggestionsContainer.style.display = 'none';}selectSuggestion(text) {this.input.value = text;this.hideSuggestions();this.performSearch(text);}highlightQuery(text) {const query = this.input.value.trim();if (!query) return text;const regex = new RegExp(`(${query})`, 'gi');return text.replace(regex, '<mark>$1</mark>');}handleKeyboard(e) {const items = this.suggestionsContainer.querySelectorAll('.suggestion-item');const current = this.suggestionsContainer.querySelector('.suggestion-item.active');switch (e.key) {case 'ArrowDown':e.preventDefault();if (current) {current.classList.remove('active');const next = current.nextElementSibling || items[0];next.classList.add('active');} else if (items.length > 0) {items[0].classList.add('active');}break;case 'ArrowUp':e.preventDefault();if (current) {current.classList.remove('active');const prev = current.previousElementSibling || items[items.length - 1];prev.classList.add('active');} else if (items.length > 0) {items[items.length - 1].classList.add('active');}break;case 'Enter':e.preventDefault();if (current) {const text = current.querySelector('.suggestion-text').textContent;this.selectSuggestion(text);} else {this.performSearch(this.input.value);}break;case 'Escape':this.hideSuggestions();break;}}performSearch(query) {console.log('执行搜索:', query);// 这里实现实际的搜索逻辑}
}// 初始化搜索建议
const searchSuggestion = new SearchSuggestion('searchInput', 'suggestions');

最佳实践

1. 安全性考虑

// CSRF 防护
function getCSRFToken() {return document.querySelector('meta[name="csrf-token"]').getAttribute('content');
}// 带 CSRF 令牌的请求
async function secureRequest(url, options = {}) {const defaultHeaders = {'X-CSRF-TOKEN': getCSRFToken(),'Content-Type': 'application/json'};return fetch(url, {...options,headers: {...defaultHeaders,...options.headers}});
}// 验证响应数据
function validateResponse(data, schema) {// 简单的数据验证示例for (let key in schema) {if (schema[key].required && !data.hasOwnProperty(key)) {throw new Error(`缺少必需字段:${key}`);}if (data[key] && schema[key].type && typeof data[key] !== schema[key].type) {throw new Error(`字段类型错误:${key}`);}}return true;
}

2. 性能优化

// 请求去重
class RequestDeduplicator {constructor() {this.pendingRequests = new Map();}async request(key, requestFn) {if (this.pendingRequests.has(key)) {return this.pendingRequests.get(key);}const promise = requestFn().finally(() => {this.pendingRequests.delete(key);});this.pendingRequests.set(key, promise);return promise;}
}const deduplicator = new RequestDeduplicator();// 使用示例
async function getUser(id) {return deduplicator.request(`user-${id}`, () => fetch(`/api/users/${id}`).then(r => r.json()));
}// 多次调用只会发起一次请求
getUser(1);
getUser(1);
getUser(1);

3. 错误监控

// 全局错误监控
class ErrorMonitor {constructor() {this.errors = [];this.maxErrors = 100;}log(error, context = {}) {const errorInfo = {message: error.message,stack: error.stack,timestamp: new Date().toISOString(),url: window.location.href,userAgent: navigator.userAgent,context};this.errors.push(errorInfo);// 保持错误日志数量if (this.errors.length > this.maxErrors) {this.errors.shift();}// 上报错误(可选)this.reportError(errorInfo);}async reportError(errorInfo) {try {await fetch('/api/errors', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(errorInfo)});} catch (e) {console.error('错误上报失败:', e);}}getErrors() {return this.errors;}
}const errorMonitor = new ErrorMonitor();// 包装 fetch 以监控错误
async function monitoredFetch(url, options = {}) {try {const response = await fetch(url, options);if (!response.ok) {const error = new Error(`HTTP ${response.status}: ${response.statusText}`);errorMonitor.log(error, { url, options, status: response.status });throw error;}return response;} catch (error) {errorMonitor.log(error, { url, options });throw error;}
}

4. 通用工具函数

// Ajax 工具库
const AjaxUtils = {// 构建查询字符串buildQuery(params) {return new URLSearchParams(params).toString();},// 解析响应头parseHeaders(response) {const headers = {};for (let [key, value] of response.headers.entries()) {headers[key] = value;}return headers;},// 检查网络状态isOnline() {return navigator.onLine;},// 等待网络恢复waitForOnline() {return new Promise(resolve => {if (this.isOnline()) {resolve();} else {const handler = () => {if (this.isOnline()) {window.removeEventListener('online', handler);resolve();}};window.addEventListener('online', handler);}});},// 格式化文件大小formatFileSize(bytes) {if (bytes === 0) return '0 Bytes';const k = 1024;const sizes = ['Bytes', 'KB', 'MB', 'GB'];const i = Math.floor(Math.log(bytes) / Math.log(k));return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];}
};

总结

Ajax 学习路径

  1. 掌握基础 - XMLHttpRequest 和 Fetch API
  2. 理解概念 - 同步、异步、状态码、错误处理
  3. 实践应用 - 表单提交、文件上传、数据获取
  4. 高级技巧 - 缓存、重试、并发控制、请求取消
  5. 项目实战 - 结合实际业务场景

开发建议

  • 优先使用 Fetch API,语法更简洁
  • 总是处理错误,提供友好的用户体验
  • 使用 async/await,代码更易读
  • 实现加载状态,让用户知道正在处理
  • 适当使用缓存,提升性能
  • 考虑网络状况,处理离线场景

调试技巧

// 在浏览器控制台查看网络请求
// 1. 打开开发者工具 (F12)
// 2. 切换到 Network 选项卡
// 3. 重新发起请求,查看详细信息// 使用 console.log 调试
fetch('/api/data').then(response => {console.log('响应状态:', response.status);console.log('响应头:', response.headers);return response.json();}).then(data => {console.log('响应数据:', data);});

记住:Ajax 是现代 Web 开发的核心技术,多练习、多实战才能真正掌握! 🚀

http://www.dtcms.com/wzjs/224959.html

相关文章:

  • 建设银行网站用户名怎么查长沙专业网站制作
  • wordpress商店展示seo发包排名软件
  • 杭州富阳网站建设公司百度网站提交入口网址
  • wordpress 添加过滤器免费百度seo引流
  • 怎么做付费的小说网站杭州上城区抖音seo有多好
  • 网站开发项目的规划与设计文档小红书seo软件
  • 东台企业网站建设百度标记号码认证平台
  • 网站推广都有哪些江苏seo排名
  • 通付盾 网站公司建设百度seo和谷歌seo有什么区别
  • 网站建设seo优化推广北京最新发布信息
  • 推荐常州微信网站建设做推广的公司一般都叫什么
  • 网站建设知识点百度建站云南服务中心
  • 网站被盗用seo是什么地方
  • 杂谈发现一只网站是你们谁做的军事新闻俄乌最新消息
  • 北京丰台区网站建设公司百度广告运营
  • 政府门户网站建设意义石家庄关键词排名提升
  • 成都网站开发免费广告网
  • 企业简介封面设计专业seo站长工具全面查询网站
  • 做烘焙原材料在哪网站买短视频代运营费用明细
  • php网站怎么做缓存网页推广平台
  • 知晓程序网站怎么做免费做网站软件
  • 自己做的网站可以挂在哪里市场调研报告范文3000字
  • 1688网站建设与维护上海优化公司排行榜
  • 承德网站建设电话河源seo
  • 个人计算机做服务器建网站上海专业做网站
  • 给装修公司做推广的网站微商怎么引流被别人加
  • 专做网站的公司外链发布软件
  • 专业武汉网站建设公司排名夸克搜索引擎
  • 联英人才网重庆招聘网泰州百度关键词优化
  • 国内做的比较大的外贸电商网站长沙专业seo优化公司