JavaScript中如何同步执行数据库查询?getSetting函数返回undefined原因及解决
问题拆解与解决办法
先看你贴的这段代码:
let positionSettings = require('setting'); function getSetting(element) { let setting; positionSettings.find({element: element}, function (err,docs) { console.log(docs[0].current); // output the value setting = docs[0].current; }); return setting; } $(document).on("click", "#save" , function(e) { console.log(getSetting("abc")); // Output undefined });
为啥getSetting()会返回undefined?
核心原因就是异步操作的执行顺序问题:positionSettings.find()是个异步方法——它发起数据库查询后,不会等着结果回来,而是直接往下走,执行return setting;这行代码。这时候回调函数里的setting = docs[0].current;还没执行呢(数据库查询还没完成),所以setting还是初始的undefined,自然就返回这个值了。
说白了,你的return跑在数据库结果回来之前,相当于你刚下单就问商家要货,肯定拿不到啊!
怎么正确拿到设置值?
JavaScript里处理异步逻辑,现在主流有三种方案,按易用性和现代程度排序:
1. Promise + async/await(最推荐的写法)
如果你的setting模块本身不支持Promise,先把回调式的find方法包成Promise:
let positionSettings = require('setting'); // 把回调风格的find转换成Promise function findSetting(element) { return new Promise((resolve, reject) => { positionSettings.find({element: element}, (err, docs) => { if (err) return reject(err); // 出错就抛出错误 resolve(docs[0].current); // 成功就返回结果 }); }); } // 用async/await让异步代码看起来像同步一样 async function getSetting(element) { try { const setting = await findSetting(element); return setting; } catch (err) { console.error('查询设置出错:', err); // 这里可以返回默认值或者抛出错误,根据你的需求来 return null; } } // 调用的时候也要用async/await,因为getSetting现在是异步函数了 $(document).on("click", "#save", async function(e) { const setting = await getSetting("abc"); console.log(setting); // 现在能拿到正确的结果啦 });
2. 用回调函数(传统写法)
如果你习惯老的回调风格,也可以直接把后续逻辑放到回调里,或者让getSetting接受一个回调参数:
let positionSettings = require('setting'); // 让getSetting接受一个回调函数,查询完成后调用它 function getSetting(element, callback) { positionSettings.find({element: element}, (err, docs) => { if (err) return callback(err); // 把错误传给回调 const setting = docs[0].current; callback(null, setting); // 把结果传给回调 }); } $(document).on("click", "#save", function(e) { getSetting("abc", (err, setting) => { if (err) { console.error('查询出错:', err); return; } console.log(setting); // 这里就能拿到正确的值了 }); });
3. 同步API(非常不推荐)
有些数据库驱动会提供同步版本的方法,比如findSync之类的,但我真的不建议用——同步操作会把整个JavaScript线程卡死,浏览器页面会失去响应,Node.js服务也会没法处理其他请求,除非是在启动初始化这种特殊场景,否则千万别碰。
内容的提问来源于stack exchange,提问作者Narayan Choudhary
相关产品推荐
相关产品推荐

