欢迎光临
我们一直在努力

JQuery学习文档(五)

第五部分:异步通信与后端交互

目录

第五部分:异步通信与后端交互

5.1. Ajax 与网络请求

5.1.1. 核心方法 $.ajax():配置项全解

5.1.2. 生命周期钩子:beforeSend, success, error, complete

5.1.3. 全局 Ajax 事件:ajaxStart, ajaxStop 与全局加载遮罩

5.2. 快捷方法与工具

5.2.1. $.get(), $.post(), $.getJSON(), $.getScript()

1. GET 请求获取数据

2. POST 请求提交数据

3. getJSON:专门获取 JSON 数据,自动解析

4. getScript:动态加载并执行 JS 脚本

5.2.2. 序列化工具:$.param() 与表单序列化 .serialize()

方法一:直接序列化整个表单

方法二:序列化普通对象

5.3. Promise 与 Deferred 对象

5.3.1. Deferred 对象创建:$.Deferred() 与状态管理

5.3.2. Promise 风格调用:解决回调地狱

传统写法

Promise 链式写法

5.3.3. 并发控制:$.when(…).done() 实现多请求并行

定义三个并行的异步请求

并发执行,全部成功后才触发 done

5.3.4. jQuery Promise vs ES6 Promise 的差异与兼容性

jQuery Promise 的错误处理缺陷示例

ES6 Promise 的改进

5.4. 跨域与安全

5.4.1. CORS 跨域配置:crossDomain 参数与 withCredentials 凭证携带

5.4.2. 安全防护:XSRF/CSRF Token 处理策略与 XSS 防御

防御策略对比

CSRF Token 处理

XSS 防御示例

5.4.3. 历史遗留:JSONP 原理回顾(现代开发已弃用)

5.1. Ajax 与网络请求

5.1.1. 核心方法 $.ajax():配置项全解

$.ajax() 是 jQuery 异步通信体系的基石,提供了高度可配置的 HTTP 请求能力。

核心配置项

类型/默认值

功能说明

url

String

请求的目标地址,后端 API 端点。

method / type

String (GET)

HTTP 请求方法,如 GETPOSTPUTDELETE

data

Object / String

发送到服务器的数据,jQuery 会自动转换为查询字符串或请求体。

dataType

String (json)

预期服务器返回的数据类型,常用 jsonhtmltext

contentType

String

发送数据时的编码类型,默认 application/x-www-form-urlencoded

headers

Object

自定义请求头,常用于身份验证。

timeout

Number

请求超时时间(毫秒),超时后触发 error 回调。

作为底层方法,它不仅支持基础的 GET/POST 请求,还能精细控制缓存、头信息、数据类型转换等高级行为,是构建复杂 Web 应用的核心接口。

/* 完整的 $.ajax() 配置示例 */

$.ajax({

    url: '/api/user/profile',

    method: 'POST',

    dataType: 'json', /* 预期后端返回JSON,jQuery自动解析 */

    data: { id: 1001, action: 'update' }, /* 发送的对象数据 */

    headers: {

        'Authorization': 'Bearer token_xxxx' /* 携带身份令牌 */

    },

    timeout: 5000, /* 5秒超时保护 */

    success: function(response) {

        console.log('数据获取成功:', response);

    },

    error: function(xhr, status, err) {

        console.error('请求失败:', status, err);

    }

});

这就好比寄送一个重要包裹。

你需要填写收件地址、选择快递方式,如果包裹易碎还需要贴上特殊标签。

$.ajax() 就是那个详尽的快递单,通过勾选不同的配置项,确保数据能够按照预定方式安全抵达目的地或获得回执。

5.1.2. 生命周期钩子:beforeSend, success, error, complete

一个完整的 Ajax 请求如同一次外交活动,包含准备、成功/失败、收尾四个阶段。

钩子函数

触发时机

典型应用场景

beforeSend

请求发送前

禁用提交按钮、显示 Loading 动画、修改请求头。

success

请求成功时

解析数据、渲染页面、提示操作成功。

error

请求失败时

错误日志上报、提示用户重试、处理 404/500 状态。

complete

请求完成时 (无论成败)

隐藏 Loading 动画、恢复按钮状态、执行清理逻辑。

jQuery 提供了对应的生命周期钩子,允许开发者在特定时间点介入,实现诸如加载动画控制、权限拦截等逻辑。

$.ajax({

    url: '/api/submit',

    type: 'POST',

    data: $('#form').serialize(),

    beforeSend: function() {

        /* 请求发出前:防止用户重复点击,展示加载状态 */

        $('#submitBtn').prop('disabled', true).text('提交中…');

        $('#loading').show();

    },

    success: function(res) {

        /* 业务逻辑成功 */

        showToast('提交成功!');

    },

    error: function(xhr) {

        /* 处理网络错误或服务器报错 */

        showToast('服务器开小差了:' + xhr.status);

    },

    complete: function() {

        /* 无论成功失败,都要恢复界面状态 */

        $('#submitBtn').prop('disabled', false).text('提交');

        $('#loading').hide();

    }

});

想象一场正式的宴会:

  • beforeSend 是宴会前的筹备工作,检查场地和邀请函;
  • success 是宴会顺利进行,宾主尽欢;
  • error 是中途发生意外,如停电或食材问题;
  • complete 则是宴会结束后的收尾工作,无论过程如何,场地都需要清理复原,以便迎接下一次活动。

5.1.3. 全局 Ajax 事件:ajaxStart, ajaxStop 与全局加载遮罩

在单页应用(SPA)或复杂的页面交互中,往往同时存在多个 Ajax 请求。

为了避免每个请求都要单独处理加载状态,jQuery 提供了全局事件监听机制,允许在 document 对象上统一监控所有 Ajax 请求的开始与结束。

/* 绑定全局事件监听器 */

$(document).ajaxStart(function() {

    /* 只要页面上有任意 Ajax 请求开始,且无其他未完成请求,即触发 */

    $('#global-spinner').fadeIn(200);

});

$(document).ajaxStop(function() {

    /* 当页面上所有 Ajax 请求都完成时触发 */

    $('#global-spinner').fadeOut(200);

});

/* 如果某个特定请求不想触发全局事件,可配置 global: false */

$.ajax({

    url: '/api/ping',

    global: false, /* 静默请求,不触发全局 Loading */

    success: function() { /* … */ }

});

事件名称

触发条件

备注说明

ajaxStart

第一个请求开始时

适合启动全局遮罩。

ajaxSend

每个请求发送前

可用于记录日志。

ajaxSuccess

每个请求成功时

可统一预处理响应数据。

ajaxError

每个请求失败时

可统一拦截错误码(如 401 跳转登录)。

ajaxComplete

每个请求完成时

无论成败均触发。

ajaxStop

所有请求结束时

适合关闭全局遮罩。

这就像是机场的塔台指挥系统。

无论天上飞着多少架飞机,塔台都有全局的雷达监控屏。

只要有一架飞机起飞,雷达屏就进入工作状态;

直到最后一架飞机降落,屏幕才恢复平静。

这种“全局视野”让开发者无需关注每架飞机的具体调度,也能掌握整体繁忙状态。

5.2. 快捷方法与工具

5.2.1. $.get(), $.post(), $.getJSON(), $.getScript()

对于简单的 GET 或 POST 请求,$.ajax() 的完整配置显得过于繁琐。

jQuery 封装了一系列快捷方法,将常用配置内置,简化了代码书写,提高了开发效率。

1. GET 请求获取数据

$.get('/api/articles', { page: 1 }, function(response) {

    console.log('获取文章列表:', response);

}, 'json');

2. POST 请求提交数据

$.post('/api/login', { user: 'admin', pwd: '123456' }, function(res) {

    if (res.token) {

        localStorage.setItem('token', res.token);

    }

});

3. getJSON:专门获取 JSON 数据,自动解析

$.getJSON('/api/config.json', function(data) {

    /* data 已自动转为 JS 对象,无需 JSON.parse */

    console.log('配置项:', data.version);

});

4. getScript:动态加载并执行 JS 脚本

$.getScript('/js/plugin.js', function() {

    /* 脚本加载完毕并执行后回调 */

    initPlugin(); /* 此时 plugin.js 中的函数已可用 */

});

方法

等效 $.ajax() 配置

典型用途

$.get(url, data, success)

{ method: 'GET' }

查询数据、获取页面片段。

$.post(url, data, success)

{ method: 'POST' }

表单提交、登录注册。

$.getJSON(url, success)

{ dataType: 'json' }

加载配置文件、API 数据交互。

$.getScript(url, success)

{ dataType: 'script' }

按需加载第三方库、延迟加载。

这些快捷方法就像是便利店里的“预调饮料”。

相比于 $.ajax() 这个专业的咖啡机(需要自己磨豆、调温、萃取),快捷方法直接提供了一杯调好的美式或拿铁,开盖即饮,适合不需要个性化定制的大多数标准场景。

5.2.2. 序列化工具:$.param() 与表单序列化 .serialize()

在前后端交互中,前端经常需要将表单数据或 JS 对象转换为 URL 编码的字符串格式。

jQuery 提供了 .serialize() 和 $.param() 两个工具方法,极大简化了数据拼接的工作。

方法

作用对象

输出格式示例

.serialize()

jQuery 表单元素集合

name=John&age=20

.serializeArray()

jQuery 表单元素集合

[{name:'name', value:'John'}, …]

$.param()

普通 JS 对象或数组

user[name]=John&user[age]=20

场景:复杂的表单提交

<form id="register">

    <input name="username" value="test">

    <input name="password" value="123">

    <input name="hobbies[]" value="coding"> <!– 数组类型 –>

    <input name="hobbies[]" value="reading">

</form>

方法一:直接序列化整个表单

$('#register').serialize();

/* 输出: username=test&password=123&hobbies%5B%5D=coding&hobbies%5B%5D=reading */

方法二:序列化普通对象

var filterParams = { status: 'active', role: 'admin' };

$.param(filterParams);

/* 输出: status=active&role=admin */

/* 应用:直接用于 Ajax 请求 */

$.post('/api/update', $('#register').serialize(), function(res) {

    /* … */

});

这就像是搬家公司打包行李。

  • .serialize() 是标准的打包箱服务,扫描整个房间(表单),把所有散落的物品整齐地码进箱子,并贴上标签。
  • $.param() 则是人工打包,你可以自定义把哪些零散物品(JS 对象属性)打包成特定的形状,方便运输给后端。

5.3. Promise 与 Deferred 对象

5.3.1. Deferred 对象创建:$.Deferred() 与状态管理

jQuery 的 $.Deferred() 是异步编程的核心模型,它引入了状态管理的概念。

状态

含义

触发方法

可绑定回调

pending

初始状态,操作未完成

progress()

resolved

操作成功

resolve()

done()

rejected

操作失败

reject()

fail()

一个 Deferred 对象有三种状态:待定、已解决和已拒绝,且状态一旦改变就不可逆转,这是实现异步链式调用的基础。

/* 创建一个耗时任务的 Promise 封装 */

function asyncTask() {

    var dtd = $.Deferred(); /* 创建延迟对象 */

    setTimeout(function() {

        var success = Math.random() > 0.5;

        if (success) {

            dtd.resolve('任务完成'); /* 标记为成功 */

        } else {

            dtd.reject('出错了'); /* 标记为失败 */

        }

    }, 1000);

    return dtd.promise(); /* 返回只读的 Promise 对象,防止外部修改状态 */

}

/* 使用示例 */

asyncTask()

    .done(function(msg) { console.log('成功:', msg); })

    .fail(function(err) { console.log('失败:', err); });

这就好比购买了一张演唱会门票。

  • 演唱会开始前,状态是“待定”;
  • 演出如期举行,状态变为“已解决”,你可以进场观看;
  • 若演出取消,状态变为“已拒绝”,你可以申请退款。
  • 一旦演出结束或取消,这个历史事实就无法改变,不能说昨天“已解决”的演出今天突然变成“已拒绝”了。

5.3.2. Promise 风格调用:解决回调地狱

传统的 Ajax 回调写法在处理多层嵌套请求时会产生“回调地狱”。

jQuery 的 Deferred 对象支持链式调用,通过 .then() 方法将异步操作拉平,使代码逻辑线性化、可读性大幅提升。

传统写法

$.ajax({

    url: '/api/user',

    success: function(user) {

        $.ajax({

            url: '/api/orders',

            data: { userId: user.id },

            success: function(orders) {

                $.ajax({

                    url: '/api/details',

                    data: { orderId: orders[0].id },

                    success: function(details) {

                        console.log('最终详情:', details); /* 嵌套三层,难以维护 */

                    }

                });

            }

        });

    }

});

Promise 链式写法

$.ajax({ url: '/api/user' })

    .then(function(user) {

        return $.ajax({ url: '/api/orders', data: { userId: user.id } });

    })

    .then(function(orders) {

        return $.ajax({ url: '/api/details', data: { orderId: orders[0].id } });

    })

    .done(function(details) {

        console.log('最终详情:', details); /* 逻辑清晰,层层递进 */

    })

    .fail(function(err) {

        console.error('任一步骤出错,统一在此捕获:', err);

    });

回调地狱就像是把车开进了盘山公路,每一个弯道(异步操作)都套在上一个弯道里面,绕得人晕头转向。

Promise 链式调用则是修了一条直线隧道,无论中间经过多少个站点,从外面看都是一条笔直的道路,从起点直达终点,中途任何故障也都有统一的出口处理。

5.3.3. 并发控制:$.when(…).done() 实现多请求并行

在需要同时等待多个异步任务全部完成的场景下(如同时加载配置、用户信息和权限列表),$.when() 提供了类似 ES6 Promise.all 的并发控制能力,显著减少等待时间。

定义三个并行的异步请求

var req1 = $.get('/api/config');

var req2 = $.get('/api/user');

var req3 = $.get('/api/permissions');

并发执行,全部成功后才触发 done

$.when(req1, req2, req3).done(function(data1, data2, data3) {

    /* 注意:每个参数是一个数组 [data, textStatus, jqXHR] */

    console.log('配置:', data1[0]);

    console.log('用户:', data2[0]);

    console.log('权限:', data3[0]);

    initApp(); /* 所有前置数据就绪,启动应用 */

}).fail(function(err) {

    console.error('其中一个请求失败,初始化中止');

});

这就像是请客吃饭准备了三道菜。

厨师($.when)不需要等第一道菜做完才开始做第二道,而是三个灶台同时开火。

只有当三道菜全部做好了,才会通知“上菜”。

如果任何一道菜做坏了,整个宴席可能就要推迟或取消。

5.3.4. jQuery Promise vs ES6 Promise 的差异与兼容性

虽然 jQuery 的 Deferred 早于 ES6 Promise 出现,但两者在 API 设计和错误处理上存在微妙差异。

现代开发中推荐优先使用 ES6 标准,但在维护旧项目时仍需理解其区别。

特性

jQuery Deferred/Promise

ES6 Promise

错误捕获

若回调中报错,会静默吞掉,需手动 try-catch

自动捕获异常,触发后续 reject

状态触发

不仅有 resolve/reject,还有 notify/progress

无进度通知机制

回调注册

.done().fail().always()

.then().catch().finally()

then 返回值

返回新的 Deferred 对象

返回新的 Promise 对象

兼容性

兼容 IE 等老旧浏览器

Polyfill 支持

jQuery Promise 的错误处理缺陷示例

$.ajax({ url: '/api/data' })

    .done(function(data) {

        /* 这里的代码如果报错,外部的 .fail 无法捕获 */

        JSON.parse('invalid json');

    })

    .fail(function() {

        /* 这里无法捕获 done 中的错误 */

    });

ES6 Promise 的改进

fetch('/api/data')

    .then(res => {

        JSON.parse('invalid json'); /* 抛出错误 */

    })

    .catch(err => {

        /* 可以正常捕获到 then 中的异常 */

        console.error(err);

    });

jQuery Promise 就像是老式的模拟对讲机,功能丰富甚至能发信号,但在抗干扰(错误处理)方面表现一般。

ES6 Promise 则是现代数字通信协议,虽然接口更简洁,但具备更健壮的异常处理机制。

在现代开发中,建议将 jQuery Ajax 返回的 Promise 转换为 ES6 标准,以保证一致性。

5.4. 跨域与安全

5.4.1. CORS 跨域配置:crossDomain 参数与 withCredentials 凭证携带

浏览器的同源策略默认阻止跨域请求,CORS(跨域资源共享)是现代标准解决方案。

配置项

作用

使用场景

crossDomain

强制跨域请求 (默认自动检测)

极少手动设置,除非同域请求需强制跨域行为

xhrFields

设置原生 XHR 对象属性

withCredentials: true 用于携带 Cookie

headers

添加自定义头信息

满足服务器 CORS 预检要求

jQuery 在处理跨域时,虽然大部分工作由浏览器和服务器完成,但在携带 Cookie 等凭证时需显式配置。

/* 跨域请求并携带 Cookie (如 SSO 单点登录场景) */

$.ajax({

    url: 'https://api.example.com/user/info',

    type: 'GET',

    xhrFields: {

        withCredentials: true /* 允许跨域请求携带身份凭证 */

    },

    success: function(res) {

        console.log('用户信息:', res);

    }

});

注意:

服务器端必须配置 Access-Control-Allow-Credentials: true

且 Access-Control-Allow-Origin 不能为 *,必须指定域名

跨域请求就像是去另一个国家的海关。

普通请求只允许你把信扔过去。

但如果你需要“带行李”过去,就必须提前申请签证并走特殊通道。

withCredentials 就是这个特殊通道的通行证,允许你带着 Cookie 这个“行李”通过海关。

5.4.2. 安全防护:XSRF/CSRF Token 处理策略与 XSS 防御

Web 安全是前后端交互不可忽视的一环。

CSRF(跨站请求伪造)利用用户已认证的身份发起恶意请求,XSS(跨站脚本攻击)则通过注入恶意脚本窃取信息。

防御策略对比

攻击类型

攻击原理

jQuery 防御手段

CSRF

伪造用户请求

请求头携带 X-XSRF-TOKEN

XSS

注入恶意脚本

避免拼接 HTML,使用 .text() 而非 .html()

CSRF Token 处理

从 Cookie 或 Meta 标签获取 Token 并放入请求头

var csrfToken = $('meta[name="csrf-token"]').attr('content');

$.ajaxSetup({

    headers: {

        'X-XSRF-TOKEN': csrfToken /* 全局配置,每个请求自动带上 */

    }

});

XSS 防御示例

var userInput = '<script>alert("恶意代码")</script>';

/* 危险写法:直接拼接 HTML,会执行脚本 */

// $('#content').html(userInput);

/* 安全写法:转义为文本,只展示不执行 */

$('#content').text(userInput);

/* 输出纯文本: <script>alert("恶意代码")</script> */

CSRF 就像是伪造的银行转账单,攻击者利用你已经登录的状态,偷偷提交了转账申请。

防御的办法就是在每一张真的转账单上盖一个特殊的、随机的“骑缝章”,这个章只有你自己知道,攻击者伪造的假单子上没有这个章,银行就会拒绝受理。

5.4.3. 历史遗留:JSONP 原理回顾(现代开发已弃用)

在 CORS 标准普及之前,JSONP 是实现跨域的主流手段。

特性

JSONP

CORS (现代标准)

核心原理

利用 <script> 标签

浏览器原生支持

请求方式

仅支持 GET

支持所有 HTTP 方法

错误处理

极弱,无法捕获 404/500

完善的状态码处理

安全性

较低,存在被劫持风险

较高,支持预检机制

现代地位

已弃用

主流标准

它利用 <script> 标签不受同源策略限制的特性,通过动态创建标签请求 JSON 数据。

虽然现代开发已很少使用,但在维护老旧系统时仍需了解其原理。

jQuery 的 JSONP 调用方式

$.ajax({

    url: 'https://api.legacy.com/data',

    dataType: 'jsonp', /* 声明为 JSONP 模式 */

    jsonpCallback: 'handleResponse', /* 指定回调函数名 */

    success: function(data) {

        console.log('收到数据:', data);

    }

});

/* 底层原理模拟 */

function loadJSONP(url) {

    var script = document.createElement('script');

    script.src = url + '?callback=handleResponse';

    document.body.appendChild(script); /* 插入页面即发起请求 */

}

/* 服务器返回:handleResponse({ "data": "…" }); */

JSONP 就像是“走私”通道。

正规的 HTTP 请求关卡重重,而 JSONP 利用 <script> 标签这个不受检查的“绿色通道”把数据运进来。

它的形式必须是 callback(data),就像是一辆必须贴着特定标签的车才能通过。

现在海关升级了,正规通道开放且更安全,走私通道自然就没人走了。

赞(0)
未经允许不得转载:171主机测评 » JQuery学习文档(五)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址