Node.js中异步回调修改条件的while循环无限循环问题及解决方案
解决Node.js中异步回调导致while循环无限执行的问题
你遇到的问题本质是同步循环和异步操作的执行顺序冲突:while是同步语句,会瞬间跑完无数次循环,而db.query的回调要等数据库操作完成才会执行——这时候unique变量还没被修改,循环早就进入无限状态了。
先拆解下原代码的执行流程:
unique初始为true,进入while循环- 同步执行
console.log("Inside Loop")、生成id、拼接SQL - 调用
db.query,但这个操作是异步的,回调函数会被放到事件队列里,当前同步代码(while循环)继续执行 - 因为
unique还是true,立刻进入下一次循环,重复步骤2-3,直到内存耗尽或者你手动终止程序 - 直到很久以后,数据库的查询结果才回来,回调执行修改
unique,但这时候循环早已经疯跑起来了,根本没用
接下来给你两种靠谱的解决方案:
方案1:用递归函数替代while循环
递归的思路是:每次异步操作完成后,再决定是否继续执行下一次尝试,这样就能保证每次操作都等上一次异步回调完成。
let name = "your-name-here"; // 替换为你的实际变量 let newURL = "your-new-url"; // 替换为你的实际变量 function tryInsert() { console.log("Inside Loop"); let id = random.generate(5); let u_query = "Insert into table_db (id, name) values ("+db.escape(id)+", "+db.escape(name)+")"; db.query(u_query, (error, results, fields) => { console.log("Inside Query"); if(error) { if(error.code !== 'ER_DUP_ENTRY') { throw error; // 非重复错误直接抛出 } else { // ID重复了,递归调用再试一次 tryInsert(); } } else { // 插入成功,停止递归并返回结果 res.send("Shorted URL : "+newURL); } }); } // 启动第一次插入尝试 tryInsert();
方案2:用Async/Await(更现代、易读的方式)
把db.query包装成Promise,然后在async函数里用while循环,这样每次循环都会等待异步操作完成,再判断是否继续。
首先包装db.query为Promise:
function queryPromise(sql) { return new Promise((resolve, reject) => { db.query(sql, (error, results, fields) => { if(error) reject(error); else resolve(results); }); }); }
然后用async/await写循环:
async function insertUniqueId() { let name = "your-name-here"; let newURL = "your-new-url"; while(true) { console.log("Inside Loop"); let id = random.generate(5); let u_query = "Insert into table_db (id, name) values ("+db.escape(id)+", "+db.escape(name)+")"; try { await queryPromise(u_query); // 插入成功,跳出循环并返回结果 res.send("Shorted URL : "+newURL); break; } catch(error) { if(error.code !== 'ER_DUP_ENTRY') { // 非重复错误,抛出并终止程序 throw error; } // ID重复,什么都不做,继续下一次循环 } } } // 执行函数 insertUniqueId();
额外提示
- 建议给递归/循环加个最大尝试次数(比如最多试10次),避免极端情况下无限尝试消耗资源
- 拼接SQL时优先用参数化查询(比如
db.query('INSERT INTO table_db (id, name) VALUES (?, ?)', [id, name])),比手动db.escape更安全简洁
内容的提问来源于stack exchange,提问作者Kartik
相关产品推荐
相关产品推荐

