Ajax更新的received变量函数外未读取致死循环,求解决办法
问题出在异步操作的同步陷阱上!
老兄,你遇到的核心问题是Ajax请求是异步执行的,但你的while循环是同步运行的,两者完全不在一个节奏上,导致received的值根本没法影响循环判断:
- 代码一开始就进入
while (received < 10)循环,疯狂调用getMessage() - 每次调用
getMessage()时,$.ajax只是发起了请求,根本不等请求完成,直接跳到console.log(received)——这时候received还是0 - 循环跑得太快了,所有Ajax请求都还在后台pending呢,循环已经执行了N次,浏览器主线程都被循环占满了,连success回调都没机会执行,最后直接陷入无限循环
怎么解决?两种方案任你选
方案1:用递归替代while循环(适配jQuery传统写法)
既然Ajax是异步的,我们就等每次请求成功后,再判断要不要发起下一次,而不是用同步循环硬卡:
var received = 0; function getMessage() { // 先判断是否已经达到次数,到了就终止 if (received >= 10) { console.log("搞定!最终received值:", received); return; } $.ajax({ url: '/Home/getData/', type: "GET", success: function(result) { received += 1; console.log("当前received更新为:", received); // 这次请求成功了,再发起下一次 getMessage(); }, error: function() { // 别忘了加错误处理,不然请求挂了就卡住了 console.log("请求失败,终止流程"); } }); } // 启动第一次请求 getMessage();
这样每次只有当前请求完成,received更新后,才会触发下一次判断和请求,完全符合异步逻辑的节奏。
方案2:用async/await写同步风格的异步代码(更现代简洁)
如果你的项目支持ES6+语法,用async/await能把异步代码写得像同步一样,逻辑更直观:
async function fetchMessages() { let received = 0; while (received < 10) { try { // 用await等待Ajax请求完成,再继续往下走 const result = await $.ajax({ url: '/Home/getData/', type: "GET" }); received += 1; console.log("当前received值:", received); } catch (error) { console.log("请求出错了:", error); break; // 出错就终止循环,避免死等 } } console.log("所有请求完成,最终received:", received); } // 启动整个流程 fetchMessages();
这里await会让代码暂停,直到Ajax请求返回结果,所以received的更新会被while循环的条件正确感知,不会再出现无限循环的问题。
最后再划个重点
- 异步操作(Ajax、setTimeout这些)不会阻塞主线程,主线程会直接往下跑,不会等它们完成
- 同步循环(while/for)根本感知不到异步回调里的变量更新,因为循环跑完了回调都还没执行
- 处理异步逻辑要么用回调递归,要么用Promise/async/await把异步代码"变"成同步风格
内容的提问来源于stack exchange,提问作者user9788055
相关产品推荐
相关产品推荐

