Node.js中helper函数返回值设为全局变量返回[object Promise]如何解决
问题根因
你封装的getNotification是async异步函数,所有async函数执行后默认返回Promise对象,你在server.js中直接调用赋值时没有等待异步操作完成,所以全局变量存的是Promise实例而非查询结果,渲染时就会显示[object Promise]。其他控制器中可以正常返回是因为你在调用时用了await或者.then()处理了异步结果。
解决方案
根据你的业务场景可以选择以下两种方案:
方案1:服务启动时预加载通知数据,赋值全局
修改server.js代码,等待异步查询完成后再赋值全局变量,再启动服务:
global.appRoot = path.resolve(__dirname); const helpersService = require(appRoot + '/services/helpers.service'); // 自执行async函数处理异步逻辑 (async () => { // 加await等待数据库查询完成后再赋值 global.notifcations = await helpersService().getNotification(); // 原有服务启动逻辑必须放在该函数内部,确保启动时全局变量已赋值 app.listen(3000, () => { console.log('服务启动完成') }) })()
如果你的Node.js版本在v14.8及以上,支持顶层await,可以简化为:
global.appRoot = path.resolve(__dirname); const helpersService = require(appRoot + '/services/helpers.service'); global.notifcations = await helpersService().getNotification(); // 后面正常编写app.listen启动逻辑即可
方案2:渲染时动态查询(更推荐,适配通知需要实时更新的场景)
全局变量只存服务实例,不要直接存固定的查询结果,在渲染ejs模板的控制器中异步获取最新数据后传给模板:
- 修改server.js全局赋值逻辑:
global.appRoot = path.resolve(__dirname); const helpersService = require(appRoot + '/services/helpers.service'); // 全局存服务实例而非固定查询结果 global.helpers = helpersService(); // 后面正常启动服务 app.listen(3000)
- 在对应路由的控制器中查询数据再渲染:
// 渲染页面对应的控制器必须是async函数 async function renderNotificationPage(req, res) { const notifcations = await global.helpers.getNotification(); // 把查询结果传给ejs模板 res.render('view', { notifcations }); }
- 原有ejs模板无需修改即可正常渲染数据。
注意事项
- 如果通知是和用户身份绑定的,绝对不要存在全局变量中,全局变量是所有访问用户共享的,会出现数据串号的问题,这种情况必须使用方案2,每次请求时单独查询当前用户的通知数据。
- 你现有代码中
findStatus被写死为0,if判断永远命中成立分支,这段逻辑可以简化。
内容的提问来源于stack exchange,提问作者sam curb
相关产品推荐
相关产品推荐

