NodeJS:如何从Model通过module.exports传递异步数据?
嘿,这个坑我踩过好多次!你猜的完全没错——就是异步操作的执行顺序搞的鬼。RethinkDB的连接、查询全都是异步任务,会被Node.js放到事件循环里延后执行,而你原来的代码直接把data字段挂在模型上,同步代码早就跑完返回了,这时候异步查询还没开始呢,模板拿到的自然是undefined。
给你两种靠谱的解决方式,选你顺手的来:
方式一:用Async/Await(推荐,代码更清晰)
先重构你的模型函数,让它变成异步函数,等待数据库操作完成后再返回数据:
'use strict'; var r = require('rethinkdb'); module.exports = async function IndexModel() { try { // 等待连接建立完成 const conn = await r.connect({host: '127.0.0.1', port: 28015}); // 执行查询并获取游标 const cursor = await r.db('mydb').table('mytable').run(conn); // 把游标转换成数组(拿到所有文档) const data = await cursor.toArray(); // 用完连接记得关闭 await conn.close(); // 返回查询结果 return data; } catch (err) { console.error('数据库查询出错:', err); // 把错误抛出去,让路由层处理 throw err; } };
然后在你的路由里(比如Express路由),也要用await等待模型返回数据,再传给模板:
const express = require('express'); const router = express.Router(); const IndexModel = require('./models/indexModel'); router.get('/', async (req, res) => { try { const data = await IndexModel(); // 这里的data就是数据库查出来的真实数据了 res.render('index', { data }); } catch (err) { res.status(500).send('服务器内部错误'); } }); module.exports = router;
方式二:用Promise链式调用(兼容旧Node版本)
如果你的Node版本不支持async/await,就用Promise的链式写法:
'use strict'; var r = require('rethinkdb'); module.exports = function IndexModel() { // 返回一个Promise,让路由可以等待结果 return r.connect({host: '127.0.0.1', port: 28015}) .then(conn => { return r.db('mydb').table('mytable').run(conn) .then(cursor => cursor.toArray()) .then(data => { conn.close(); return data; }) .catch(err => { conn.close(); throw err; }); }); };
路由里用.then()处理结果:
router.get('/', (req, res) => { IndexModel() .then(data => res.render('index', { data })) .catch(err => res.status(500).send('服务器内部错误')); });
最后在Pug模板里正常使用就行
比如:
h1 我的数据库数据 if data && data.length ul each item in data li= item.yourFieldName else p 暂无数据
额外提醒两句:
- 一定要加错误处理,不然数据库出错会直接崩掉服务
- 生产环境建议用RethinkDB连接池,而不是每次查询都新建/关闭连接,效率更高
内容的提问来源于stack exchange,提问作者P. Nick
相关产品推荐
相关产品推荐

