jQuery异步请求完成后显示Div B的正确实现方案咨询
问题:点击按钮切换Div显示,异步加载完成后再展示目标Div
你遇到的场景很典型:页面有两个Div(A和B),Div B默认隐藏。Div A里只有一个按钮,点击后要隐藏Div A、显示Div B,但Div B的内容依赖多个异步REST请求,必须等所有数据都准备好才能展示它。你试了两种方案都有问题,下面我来帮你分析问题所在,再给出正确的实现方式。
先聊聊你试的两个方案的问题
方案1的无效原因
你写的$.when(renderChildPage()).done($("#B").show())有两个关键错误:
renderChildPage没有返回Promise:$.when需要接收Promise(或者jQuery的Deferred对象)才能追踪异步操作的完成状态。如果你的异步调用是$.ajax这类,得把这些请求的Promise收集起来返回,$.when才知道什么时候所有异步操作都结束。done里的代码执行时机错了:你直接写$("#B").show(),这会导致页面加载时就执行这个显示操作,而不是等异步完成后才触发。正确的写法是把$("#B").show()放进一个函数里,这样done触发时才会调用它。
方案2的自动执行问题
你写的var renderChildPage = (function () { ... })();是立即执行函数表达式(IIFE),这种语法的核心就是「定义完立刻执行」——外层的括号把函数变成表达式,最后的()就是直接调用这个函数,所以不管你有没有手动写renderChildPage(),它都会在代码执行到这一行的时候自动运行,提前填充Div B的内容。而且你点击按钮时写的renderChildPage只是引用了这个函数的返回值,根本没重新调用它。
正确的实现方案
核心思路很明确:
- 让
renderChildPage返回一个Promise,用来标识所有异步请求都完成。 - 点击按钮后先隐藏Div A,然后调用
renderChildPage,等所有异步操作完成后再显示Div B。
代码示例(适配现代jQuery/原生Promise)
$(document).ready(function() { $("#B").hide(); // 默认隐藏Div B $("#button1").click(function () { // 先隐藏Div A $("#A").hide(); // 调用异步加载函数,完成后显示Div B renderChildPage().then(function() { $("#B").show(); }).catch(function(error) { // 处理异步请求失败的情况,比如提示用户或恢复Div A显示 console.error("加载内容失败:", error); $("#A").show(); }); }); }); function renderChildPage() { // 假设有多个异步REST请求 const request1 = $.ajax("/api/first-data"); const request2 = $.ajax("/api/second-data"); // 用Promise.all等待所有请求完成 return Promise.all([request1, request2]).then(function([data1, data2]) { // 填充Div B的内容 $("#B .section1").text(data1.content); $("#B .section2").html(data2.detail); // 确保返回一个完成状态的Promise return Promise.resolve(); }); }
适配旧版jQuery(低于3.0)的写法
如果你的项目用的是旧版jQuery,可以用$.when代替Promise.all:
function renderChildPage() { const request1 = $.ajax("/api/first-data"); const request2 = $.ajax("/api/second-data"); // 用$.when等待所有请求完成 return $.when(request1, request2).done(function(data1, data2) { $("#B .section1").text(data1.content); $("#B .section2").html(data2.detail); }); }
再解释下方案2的自动执行逻辑
你写的(function () { ... })();是IIFE(立即执行函数表达式),这种写法的作用就是定义函数的同时立刻执行它:
- 外层的
(function () { ... })把函数从「声明」变成「表达式」,避免变量污染全局作用域。 - 最后的
()就是直接调用这个函数,所以不管你有没有把它赋值给renderChildPage,它都会在代码执行到这里的时候自动运行。
如果想让它变成可以手动调用的函数,只要去掉最后的()就行:
// 普通函数声明 function renderChildPage() { // 你的异步操作和内容填充代码 } // 或者函数表达式 var renderChildPage = function() { // 你的异步操作和内容填充代码 };
内容的提问来源于stack exchange,提问作者sonic boom
相关产品推荐
相关产品推荐

