在Web开发中,实现页面的局部更新和无刷新数据交互是提升用户体验的关键。AJAX(Asynchronous JavaScript and XML)作为一项核心技术,让这种交互成为可能。本文将深入讲解AJAX的原理、应用场景及实现方式。

一、AJAX基础概念

1.1 什么是AJAX

  • AJAX全称:Asynchronous JavaScript and XML(异步的JavaScript和XML)
  • 核心作用:实现浏览器和服务器的异步数据交互
  • 特点:可以在不刷新整个页面的情况下,与服务器交换数据并更新部分网页内容

XMLHttpRequest实例的创建与使用

// 1. 标准创建方式
const xhr = new XMLHttpRequest();

// 2. 兼容性写法(适配IE5/6)
function createXHR() {
    if (typeof XMLHttpRequest !== "undefined") {
        return new XMLHttpRequest();
    } else if (typeof ActiveXObject !== "undefined") {
        // IE6及以下
        if (typeof arguments.callee.activeXString !== "string") {
            const versions = [
                "MSXML2.XMLHttp.6.0",
                "MSXML2.XMLHttp.3.0",
                "MSXML2.XMLHttp"
            ];
            for (let i = 0; i < versions.length; i++) {
                try {
                    new ActiveXObject(versions[i]);
                    arguments.callee.activeXString = versions[i];
                    break;
                } catch(ex) {
                    // 跳过
                }
            }
        }
        return new ActiveXObject(arguments.callee.activeXString);
    } else {
        throw new Error("No XHR object available");
    }
}

1.2 同步与异步的区别

同步:

  • 代码按顺序执行
  • 前一个任务完成后才能执行后一个任务
  • 可能造成页面阻塞

异步:

  • 多个任务可以同时执行
  • 任务之间互不影响
  • 提高页面性能和用户体验
// 同步示例
console.log('开始');
alert('同步操作');
console.log('结束');

// 异步示例
console.log('开始');
setTimeout(() => {
    console.log('异步操作');
}, 1000);
console.log('结束');

二、AJAX状态码详解

2.1 readyState状态码

XMLHttpRequest对象的readyState属性表示请求/响应过程的当前活动阶段:

const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
    switch(xhr.readyState) {
        case 0: // UNSENT
            console.log('尚未调用open()方法');
            break;
        case 1: // OPENED
            console.log('已调用open()方法');
            break;
        case 2: // HEADERS_RECEIVED
            console.log('已接收响应头');
            break;
        case 3: // LOADING
            console.log('正在接收响应体');
            break;
        case 4: // DONE
            console.log('请求完成');
            break;
    }
};

2.2 HTTP状态码

常见的HTTP状态码及其含义:

  • 2xx 成功响应
    • 200:请求成功
    • 201:创建成功
  • 3xx 重定向
    • 301:永久重定向
    • 302:临时重定向
  • 4xx 客户端错误
    • 400:请求语法错误
    • 404:资源不存在
  • 5xx 服务器错误
    • 500:服务器内部错误

2.3 XHR对象的属性

// 1. readyState - 请求/响应过程的当前活动阶段
xhr.readyState  
// 0: 未初始化。尚未调用open()方法
// 1: 启动。已经调用open()方法,但未调用send()方法
// 2: 发送。已经调用send()方法,但尚未接收到响应
// 3: 接收。已经接收到部分响应数据
// 4: 完成。已经接收到全部响应数据

// 2. status - HTTP状态码
xhr.status  // 如:200, 404, 500等

// 3. statusText - HTTP状态说明
xhr.statusText  // 如:"OK", "Not Found"等

// 4. responseType - 响应数据类型
xhr.responseType  // "text", "json", "blob", "arraybuffer"等

// 5. response - 响应内容
xhr.response

// 6. timeout - 超时时间设置(毫秒)
xhr.timeout = 3000;

   2.4 核心方法使用

// 1. open() - 初始化请求
xhr.open("GET", "url", true);  // method, url, async
// 第三个参数true表示异步请求,false表示同步请求

// 2. send() - 发送请求
xhr.send(null);  // GET请求
xhr.send(data);  // POST请求发送数据

// 3. setRequestHeader() - 设置请求头
xhr.setRequestHeader("Content-Type", "application/json");

// 4. abort() - 终止请求
xhr.abort();

AJAX请求默认是异步的,但确实可以配置为同步。这两种模式各有适用场景

异步请求(默认)

适用场景:

  • 大多数情况下应该使用异步请求
  • 需要保持用户界面响应性的情况
  • 执行后台操作而不阻塞用户交互
  • 多个并行请求需要同时进行
  • 长时间运行的操作(如数据上传、大量数据处理)

优点:

  • 不会阻塞用户界面
  • 提供更好的用户体验
  • 允许用户继续与页面交互
  • 可以同时处理多个请求

同步请求(特殊情况)

适用场景:

  • 当后续代码严格依赖于请求结果才能继续执行
  • 需要确保按特定顺序执行的操作
  • 加载关键配置数据,必须先完成才能继续
  • 简单的脚本或原型开发,不关注用户体验
  • 在注销或页面卸载前需要保证数据已发送到服务器

注意事项:

  • 同步请求会完全阻塞浏览器界面
  • 现代浏览器已经开始不推荐或禁用同步请求
  • 会导致糟糕的用户体验,用户界面会冻结直到请求完成

最佳实践是尽可能使用异步请求,结合回调函数、Promise或async/await来处理请求完成后的逻辑,而不是使用同步请求。大多数现代浏览器已经不再推荐使用同步AJAX请求,并在控制台中发出警告。

2.5 事件处理

// 1. onreadystatechange - 请求状态变化事件
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4) {
        if (xhr.status === 200) {
            console.log(xhr.responseText);
        }
    }
};

// 2. 其他常用事件
xhr.onload = function() {
    // 请求完成时触发
};

xhr.onerror = function() {
    // 请求错误时触发
};

xhr.ontimeout = function() {
    // 请求超时时触发
};

xhr.onabort = function() {
    // 请求终止时触发
};

xhr.onprogress = function(event) {
    // 接收数据过程中周期性触发
    if (event.lengthComputable) {
        const percentComplete = (event.loaded / event.total) * 100;
        console.log(percentComplete + '% completed');
    }
};

  2.6 完整使用示例

function ajax(options) {
    const xhr = new XMLHttpRequest();
    
    // 设置超时
    xhr.timeout = options.timeout || 3000;
    
    // 监听状态变化
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4) {
            if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
                options.success && options.success(xhr.responseText);
            } else {
                options.error && options.error(xhr.status);
            }
        }
    };
    
    // 监听错误
    xhr.onerror = function() {
        options.error && options.error();
    };
    
    // 监听超时
    xhr.ontimeout = function() {
        options.timeout && options.timeout();
    };
    
    // 处理请求参数
    let url = options.url;
    if (options.method.toUpperCase() === 'GET' && options.data) {
        url += '?' + Object.entries(options.data)
            .map(([key, value]) => `${key}=${value}`)
            .join('&');
    }
    
    // 初始化请求
    xhr.open(options.method, url, true);
    
    // 设置请求头
    if (options.headers) {
        Object.entries(options.headers).forEach(([key, value]) => {
            xhr.setRequestHeader(key, value);
        });
    }
    
    // 发送请求
    if (options.method.toUpperCase() === 'POST') {
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.send(JSON.stringify(options.data));
    } else {
        xhr.send();
    }
}

// 使用示例
ajax({
    url: 'https://api.example.com/data',
    method: 'POST',
    data: {
        name: 'test',
        age: 18
    },
    headers: {
        'Authorization': 'Bearer token'
    },
    success: function(res) {
        console.log('请求成功:', res);
    },
    error: function(status) {
        console.log('请求失败:', status);
    },
    timeout: function() {
        console.log('请求超时');
    }
});

三、GET与POST请求详解

3.1 GET请求特点

  • 用于获取数据

                用于从服务器获取(拿取)数据

  • 参数通过URL传递

                在浏览器地址栏输入URL回车时,默认使用GET请求(通常用于查询操作)

  • 有缓存

                通过时间戳解决该问题

  • 传数据量较小
const xhr = new XMLHttpRequest();
xhr.open('GET', 'api/data?id=123&name=test', true);
// 解决GET请求缓存问题
xhr.open('GET', `api/data?t=${new Date().getTime()}`, true);
xhr.send();

  基本格式说明:

  1. ? - 问号后面开始是 URL 参数
  1. 参数=值 - 每个参数都是 "参数名=参数值" 的格式
  1. & - 使用 & 符号分隔多个参数
https://example.com/path?参数1=值1&参数2=值2&参数3=值3

3.2 POST请求特点

  • 用于提交数据
  • 参数通过请求体传递

                用于向服务器提交(发送)数据,多与表单提交场景搭配,通常用于创建或更新操作

  • 无缓存
  • 可传输大量数据
  • 相对更安全
const xhr = new XMLHttpRequest();
xhr.open('POST', 'api/data', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({id: 123, name: 'test'}));

3.3 http请求头和请求体是什么?

 1. 什么是 HTTP 请求头?

HTTP 请求头就是 浏览器或前端代码在发起网络请求时,附带的一些键值对信息

这些信息告诉服务器:

  • 我是谁(客户端信息)

  • 我要什么(资源、数据)

  • 我能接受什么样的响应(格式、编码)

  • 我带来的额外内容(认证信息、cookie 等)

2.内容协商相关
  • Accept: 前端能接受的返回类型,比如 application/json、text/html

  • Accept-Encoding: 支持的压缩方式(gzip、br 等)

  • Accept-Language: 支持的语言(如 zh-CN、en-US)

3.前端常设置的自定义头
  • Content-Type: 前端发出去的数据格式

    • application/json → 发送 JSON

    • application/x-www-form-urlencoded → 表单数据

    • multipart/form-data → 文件上传

  • Authorization: 携带 token 做身份认证

  • 自定义头:比如 X-Requested-With: XMLHttpRequest(表示 AJAX 请求)

 4. 前端关注请求头的场景
  • 发送 JSON、表单、文件上传 → 要设置正确的 Content-Type

  • 登录鉴权 → 要带上 Authorization 或 Cookie

  • 跨域请求 (CORS) → 会涉及 Origin、Access-Control-Request-Headers

  • 调试 & 排查问题 → 打开浏览器 Network 看请求头和响应头

5.什么是http请求体

        请求体 (Body): 是 HTTP请求里,真正要传给服务器的数据内容

         一般出现在 POST、PUT、PATCH 这类请求中,

        GET 请求通常没有请求体(参数放在 URL 上)。

📌 对比:

  • 请求头(Headers):说明“怎么传、用啥格式”。

  • 请求体(Body):就是“传什么内容”。

AJAX请求主要使用的是HTTP请求方法,HTTP协议定义的标准请求方法只有9种

GET、POST、PUT、DELETE、HEAD、OPTIONS、PATCH、CONNECT、TRACE

比较常见的 6 种请求方式:

  • GET - 用于从服务器获取数据,参数通常附加在URL后面
  • POST - 用于向服务器发送数据以创建或更新资源,数据包含在请求体中
  • PUT - 用于更新服务器上的现有资源,发送完整的资源数据
  • DELETE - 用于删除服务器上的指定资源
  • PATCH - 用于对资源进行部分更新,只发送需要修改的部分
  • HEAD - 类似于GET请求但只请求头信息,不返回响应体

具体用什么请求方式,由后端决定,后端会写一个接口文档给前端

四、接口(API)概念

接口是只返回数据而没有界面的URL地址,英文叫api(Application Programming Interface)

输入网址能在页面上显示数据的都为接口地址,简称接口

        接口链接示例:   https://jsonplaceholder.typicode.com/users 

复制到浏览器地址栏并回车即可查看接口数据

五、API接口文档示例

一个标准的接口文档应有的内容如下

基本信息 说明
接口名称 用户登录
接口描述 用户通过账号密码进行登录认证
接口URL /api/v1/user/login
请求方式 POST
开发者 张三
创建时间 2024-02-22
更新时间 2024-02-22
请求头(Headers) 是否必须 示例值 说明
Content-Type application/json 请求类型
Authorization Bearer eyJhbGciOi... 登录凭证
x-client-id web 客户端标识
请求参数(Request Body) 类型 是否必须 示例值 说明
username string zhangsan 用户名
password string md5(123456) MD5加密后的密码
captcha string a1b2c 验证码
remember boolean true 是否记住登录
响应参数(Response) 类型 说明 示例值
code number 响应码 200
message string 响应描述 "登录成功"
data.userId string 用户ID "12345"
data.username string 用户名称 "张三"
data.token string 访问令牌 "eyJhbGciOi..."
data.permissions array 权限列表 ["user:read"]
响应状态码 说明 处理建议
200 请求成功 -
400 参数错误 检查请求参数
401 未授权 检查登录状态
403 权限不足 检查用户权限
500 服务器错误 联系后端开发
5.1 请求示例

后端接口需要的参数

{
    "username": "zhangsan",
    "password": "e10adc3949ba59abbe56e057f20f883e",
    "captcha": "a1b2c",
    "remember": true
}
5.2 响应示例 

后端返回的数据

{
    "code": 200,
    "message": "登录成功",
    "data": {
        "userId": "12345",
        "username": "张三",
        "token": "eyJhbGciOi...",
        "permissions": ["user:read", "user:write"]
    }
}

   5.2 失败响应示例

接口因为某些原因没请求成功

{
    "code": 401,
    "message": "用户名或密码错误",
    "data": null
}
补充说明 内容
请求限制 接口调用频率:10次/分钟
安全要求 密码需MD5加密,必须使用HTTPS
特殊说明 Token有效期为2小时
修改记录
修改人 张三
修改时间 2024-02-22
修改内容 创建接口文档

AJAX与接口文档知识总结

核心知识点回顾

  1. AJAX三大核心
    1. XMLHttpRequest对象的创建和使用
    2. GET/POST请求的区别和应用场景
    3. 异步处理机制和状态码判断
  2. 接口规范要点
    1. 标准的接口文档结构(基本信息、请求参数、响应格式)
    2. 接口安全性考虑(请求头、鉴权方式)
    3. 错误处理机制

实际应用建议

  1. 开发实践
    1. AJAX请求建议封装统一处理函数
    2. 善用Promise处理异步请求
    3. 合理使用GET/POST:查询用GET,提交用POST
  2. 文档规范
    1. 使用统一的文档模板
    2. 保持文档及时更新
    3. 示例代码必须完整可用

重点注意事项

  1. AJAX使用注意
    1. 处理好跨域问题
    2. 注意GET请求的缓存问题
    3. 异常处理不可遗漏
  2. 接口文档维护
    1. 参数说明要清晰完整
    2. 及时更新接口变更
    3. 做好版本控制

学习建议

  • 多写demo加深理解
  • 实际项目中注意积累经验
  • 推荐使用成熟的请求库(如Axios)
  • 熟练使用接口文档工具(如Swagger)

通过掌握AJAX和规范的接口文档写法,我们能更好地进行前后端协作,提高开发效率。在实际工作中,应当注重实践和积累,不断提升自己的专业能力。

从原生AJAX到Axios

知识衔接说明

  1. 学习路径        
    • 学习原生AJAX是为了理解底层原理
    • Axios是在AJAX基础上的封装优化
    • 实际开发中推荐使用 Axios
  2. Axios的优势        
    • 自动转换JSON数据
    • 更简洁的API设计
    • 客户端支持防御XSRF
    • 请求和响应的拦截器
    • 更好的异常处理机制

官网说明

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF
实际开发建议
// 原生AJAX写法(学习理解原理)
const xhr = new XMLHttpRequest();
xhr.open('GET', '/api/users');
xhr.onreadystatechange = function() {
    if(xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
    }
};
xhr.send();

// Axios写法(实际开发使用)
axios.get('/api/users')
    .then(response => console.log(response.data))
    .catch(error => console.log(error));

学习建议

  • 先掌握AJAX原理,理解异步请求的本质
  • 再学习Axios,提高开发效率
  • 实际项目中使用Axios,遇到问题能追溯到AJAX层面解决

记住:学习原生AJAX是为了理解原理,而在实际工作中,Axios等成熟的HTTP客户端库才是首选。这样既掌握了基础原理,又能提高开发效率。

博主另一篇文章有对 axios 请求库的介绍:感兴趣可以看看 

Axios 实战:拦截器、封装与工作中的关键应用

前后端是如何配合的 博主另一篇文档

前后端联调

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐