JSON 与 AJAX

一、JSON(JavaScript Object Notation)
1. 数据类型与语法细节

支持的数据类型

基本类型:字符串(需用双引号)、数字、布尔值(true/false)、null
复杂类型:数组([])、对象({})。

严格语法规范

键名必须用双引号包裹(如 "name": "张三")。
数组元素用逗号分隔,最后一个元素后不能有多余逗号。
数字不能以0开头(如012会被解析为12),不支持八进制 / 十六进制表示。

特殊场景示例

json

{
  "timestamp": 1686528000,
  "isAdmin": null,
  "emptyArray": [],
  "nestedObject": {
    "nestedArray": [1, 2, {"key": "value"}]
  },
  "escapedString": "Hello "World" \n Newline" // 转义字符:", /, , f, 
, 
, 	
}
2. JSON 与 JavaScript 对象的区别
特性 JSON JavaScript 对象
语法限制 键名必须用双引号 键名可省略引号(非字符串键)
数据类型 无函数、Symbol、Date 等 支持全部 JS 数据类型
序列化 JSON.stringify() 需手动处理复杂类型
原型链 不保留原型链 包含原型链属性
3. JSON 解析与序列化进阶

循环引用处理

javascript

const obj = { name: '循环对象' };
obj.self = obj;
// JSON.stringify(obj) 会报错
// 解决方案:使用replacer函数过滤循环引用
JSON.stringify(obj, (key, value) => {
  if (value === obj) return '[Circular Reference]';
  return value;
});

大 JSON 数据处理

分段解析:使用JSON.parse()reviver参数逐步处理。
流式解析:Node.js 中可用JSONStream库处理 GB 级 JSON 文件。

JSON Schema 验证
使用ajv等库验证 JSON 数据格式,例如:

javascript

const Ajv = require('ajv');
const ajv = new Ajv();

const schema = {
  type: 'object',
  properties: {
    name: { type: 'string' },
    age: { type: 'number', minimum: 18 }
  },
  required: ['name', 'age']
};

const valid = ajv.validate(schema, { name: '李四', age: 20 });
if (!valid) console.log(ajv.errors);
二、AJAX(Asynchronous JavaScript and XML)
1. XMLHttpRequest(XHR)完整 API

核心方法与属性

open(method, url, async):配置请求方法、URL 和异步模式。
setRequestHeader(name, value):设置请求头(如Content-Type: application/json)。
send(data):发送请求(GET 请求data为 null,POST 请求传入 JSON 字符串)。
readyState:请求状态(0 – 未初始化,1 – 已 open,2 – 已接收头,3 – 处理中,4 – 已完成)。
status:HTTP 状态码(200 – 成功,404 – 未找到,500 – 服务器错误)。

完整请求示例

javascript

const xhr = new XMLHttpRequest();
xhr.open('POST', '/api/user', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Authorization', 'Bearer token123');

xhr.onreadystatechange = function() {
  if (xhr.readyState === 4) {
    if (xhr.status >= 200 && xhr.status < 300) {
      console.log('请求成功:', xhr.responseText);
    } else {
      console.error('请求失败:', xhr.status, xhr.statusText);
    }
  }
};

const userData = { name: '张三', email: 'zhangsan@example.com' };
xhr.send(JSON.stringify(userData));
2. Fetch API vs. XHR
特性 Fetch API XHR
API 设计 Promise 链式调用,更简洁 回调函数驱动,逻辑碎片化
默认行为 不携带 Cookies 自动携带同源 Cookies
错误处理 仅网络错误会 reject,4xx/5xx 需手动处理 所有请求状态通过回调处理
取消请求 使用AbortController xhr.abort()
流处理 支持响应体分块读取 需完整接收后处理

Fetch API 示例(带取消功能)

javascript

const controller = new AbortController();
const signal = controller.signal;

fetch('/api/data', {
  method: 'GET',
  signal,
  headers: { 'Content-Type': 'application/json' }
})
.then(response => {
  if (!response.ok) throw new Error(`HTTP错误: ${response.status}`);
  return response.json();
})
.then(data => console.log('数据:', data))
.catch(error => {
  if (error.name === 'AbortError') {
    console.log('请求已取消');
  } else {
    console.error('请求失败:', error);
  }
});

// 5秒后取消请求
setTimeout(() => controller.abort(), 5000);
3. Axios 实战进阶

拦截器应用

javascript

import axios from 'axios';

// 请求拦截器(添加token)
axios.interceptors.request.use(
  config => {
    const token = localStorage.getItem('token');
    if (token) config.headers.Authorization = `Bearer ${token}`;
    return config;
  },
  error => Promise.reject(error)
);

// 响应拦截器(处理401未授权)
axios.interceptors.response.use(
  response => response,
  error => {
    if (error.response && error.response.status === 401) {
      localStorage.removeItem('token');
      var test = '/login';
    }
    return Promise.reject(error);
  }
);

// 发送请求
axios.get('/api/products', {
  params: { category: 'electronics', limit: 10 },
  timeout: 5000 // 请求超时时间
})
.then(res => console.log(res.data))
.catch(err => console.error(err));
三、JSON 与 AJAX 结合的高级场景
1. 复杂数据交互模式

分页加载与无限滚动

javascript

let page = 1;
const loadMoreData = () => {
  axios.get('/api/posts', {
    params: { page, perPage: 20 }
  })
  .then(res => {
    const posts = res.data;
    // 渲染posts到页面
    posts.forEach(post => renderPost(post));
    page++;
    
    // 检查是否还有更多数据
    if (posts.length < 20) {
      document.getElementById('load-more').disabled = true;
      document.getElementById('load-more').textContent = '没有更多内容';
    }
  })
  .catch(err => console.error('加载失败', err));
};

// 滚动到底部时触发加载
window.addEventListener('scroll', () => {
  if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 100) {
    loadMoreData();
  }
});

WebSocket 与 AJAX 协同

AJAX 用于初始化数据加载和认证。
WebSocket 用于实时数据推送(如聊天消息、通知)。

2. 性能优化策略

请求合并(Batching)
使用Promise.all合并多个请求:

javascript

const fetchData = async () => {
  try {
    const [users, posts, comments] = await Promise.all([
      axios.get('/api/users'),
      axios.get('/api/posts'),
      axios.get('/api/comments')
    ]);
    // 处理合并后的数据
    renderDashboard(users.data, posts.data, comments.data);
  } catch (error) {
    console.error('数据加载失败', error);
  }
};

防抖与节流

javascript

// 搜索框防抖(输入停止300ms后发送请求)
function debounce(func, wait) {
  let timeout;
  return function(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(this, args), wait);
  };
}

const searchInput = document.getElementById('search-input');
const debouncedSearch = debounce(async (query) => {
  if (!query.trim()) return;
  const response = await axios.get('/api/search', {
    params: { q: query }
  });
  renderSearchResults(response.data);
}, 300);

searchInput.addEventListener('input', e => debouncedSearch(e.target.value));
3. 安全与跨域解决方案

CORS 完整配置(Node.js 示例)

javascript

// Express服务器配置CORS
const express = require('express');
const app = express();

app.use((req, res, next) => {
  // 允许的域名(*表示所有域名,生产环境建议指定具体域名)
  res.setHeader('Access-Control-Allow-Origin', '*');
  // 允许的请求方法
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  // 允许的请求头
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  // 预检请求缓存时间(秒)
  res.setHeader('Access-Control-Max-Age', '86400');
  
  // 处理OPTIONS预检请求
  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }
  
  next();
});

CSRF 防护

前端从响应头获取 CSRF Token:

javascript

// 从响应头获取X-CSRF-Token
const csrfToken = document.querySelector('meta[name="csrf-token"]').content;
// 在AJAX请求中添加Token
axios.defaults.headers.common['X-CSRF-Token'] = csrfToken;

服务器验证 Token(以 Node.js 为例):

javascript

// 使用csurf中间件
const csurf = require('csurf');
const csrfProtection = csurf({ cookie: true });

app.use(csrfProtection);

app.post('/api/transfer', (req, res) => {
  // 自动验证请求头中的X-CSRF-Token
  if (!req.csrfToken()) {
    return res.status(403).send('CSRF token missing');
  }
  // 处理转账请求...
});
四、前沿技术与发展趋势
1. JSON 相关新技术

JSON5:扩展 JSON 语法,支持注释、单引号、末尾逗号等(如{ /* 注释 */ name: 'JSON5' })。
BSON:二进制 JSON,用于 MongoDB 等数据库,支持 Date、ObjectId 等类型。
MessagePack:比 JSON 更小更快的二进制格式,适用于高并发场景(如实时通信)。

2. AJAX 的演进与替代方案

SSE(Server-Sent Events):服务器向客户端推送数据(单向通信),适用于实时通知。
GraphQL:替代 REST API 的查询语言,允许客户端按需获取数据,减少 AJAX 请求次数。
微前端:通过 AJAX 动态加载子应用,实现前端应用的模块化拆分与集成。

3. WebAssembly 与 AJAX 结合

场景:使用 WebAssembly 处理 AJAX 返回的大量数据(如科学计算、图像渲染),提升性能:

javascript

// 加载WebAssembly模块
WebAssembly.instantiateStreaming(fetch('/wasm/processor.wasm'))
  .then(({ instance }) => {
    const processData = instance.exports.process;
    
    // AJAX获取数据后交给WebAssembly处理
    fetch('/api/large-data')
      .then(res => res.arrayBuffer())
      .then(data => {
        const result = processData(new Uint8Array(data));
        // 处理结果
        renderResult(result);
      });
  });
五、面试高频问题与最佳实践
1. 常见面试题

JSON 和 JS 对象的区别?(见前文对比表格)
AJAX 请求为什么会有跨域限制?如何解决?(同源策略,CORS/JSONP/ 代理)
Fetch API 相比 XHR 有哪些优势?有哪些缺点?(Promise、流处理;错误处理、Cookies 默认行为)

2. 生产环境最佳实践

错误处理:统一封装请求函数,处理网络错误、超时、4xx/5xx 状态码。
请求取消:使用AbortController或 Axios 的CancelToken取消已发出的请求。
缓存策略:结合localStorage和 HTTP 缓存(Cache-Control)减少重复请求。
性能监控:使用PerformanceObserver记录 AJAX 请求耗时,优化慢请求。

通过深入理解 JSON 的数据结构与 AJAX 的异步交互机制,开发者可以构建更高效、更灵活的 Web 应用。随着前端技术的发展,JSON 与 AJAX 的应用场景也在不断扩展,结合新兴技术(如 WebAssembly、Serverless)将进一步提升数据交互的性能与体验。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容