Javascript 为什么异步函数不能在控制器内工作';s get()处理程序?
我正在使用Node和Express连接到SQL Server数据库。我在我的Javascript 为什么异步函数不能在控制器内工作';s get()处理程序?,javascript,node.js,express,node-mssql,Javascript,Node.js,Express,Node Mssql,我正在使用Node和Express连接到SQL Server数据库。我在我的app.js文件中这样做,该文件设置了一个global变量来创建一个到数据库的connectionPool(为了简洁起见,我省略了一些样板文件): 我有一个名为offer.js的模型文件,它就是这样做的: async function getOffersAll() { await MSSQL_MYDB.connect(); // connects to the database try {
app.js
文件中这样做,该文件设置了一个global
变量来创建一个到数据库的connectionPool
(为了简洁起见,我省略了一些样板文件):
我有一个名为offer.js
的模型文件,它就是这样做的:
async function getOffersAll() {
await MSSQL_MYDB.connect(); // connects to the database
try {
var result = await MSSQL_MYDB.request(MSSQL_MYDB).query('SELECT Top(1) * FROM [dbo].[Offer]');
return result; // returns the recordset of data
} catch (error) {
console.log(error);
} finally {
if (MSSQL_MYDB){
try {
await MSSQL_MYDB.close(); // closes the DB connection
}
catch (error) {
console.log('Error closing connection');
}
}
}
}
exports.getOffersAll = getOffersAll;
到目前为止还不错。然后我有一个控制器文件index.js
,它实际上不起作用(用注释解释):
我的问题是,为什么等待来自Offer.getOffersAll()
的结果的第一个async函数()
没有失败,但是放置在router.get('/')
处理程序中的同一个异步函数失败并出现登录错误?如果我删除var rsOffersAll=wait Offer.getOffersAll()从router.get(“/”)
处理程序中执行code>,然后页面呈现,但我当然没有数据要传递给它
即使我将测试函数的值存储在变量中并尝试将其放入router.get()
处理程序中,也会发生完全相同的情况,如下所示:
async function getOffersTest() {
return await Offer.getOffersAll();
}
router.get('/', async function(req, res) {
var rsOffersAll = await getOffersTest(); // still breaks
console.dir(rsOffersAll);
res.render('index', { pagetitle: 'Homepage'}); // still never renders
});
我的最终问题是,如何解决这个问题,使它能够正常工作,即当访问主页时,路由器等待数据从数据库返回,然后我可以将其传递到我的视图,或者只要打印到控制台就可以了?因为这一行global.MSSQL\u MYDB=new MSSQL.ConnectionPool(DB\u MYDB\u Config)代码>,
当您在路由器之外执行此代码时
(async function () {
var rsOffersAll = await Offer.getOffersAll();
console.dir(rsOffersAll); // works great! recordset rsOffersAll is printed to console
})();
getOffersAll可以访问全局变量,
并且您可以在线路中成功连接数据库,等待MSSQL_MYDB.connect()//代码>
但对于路由器,全局作用域是当前的module.exports对象,而不是全局对象
解决方案
您可以像这样在应用程序中设置MSSQL\u MYDB
app.set('MSSQL\u MYDB')
然后你可以在下面的函数中得到同样的变量
router.get('/', async function(req, res) {
const MSSQL_MYDB = req.app.get('MSSQL_MYDB')
var rsOffersAll = await getOffersTest(MSSQL_MYDB );
console.dir(rsOffersAll);
res.render('index', { pagetitle: 'Homepage'}); // still never renders
});
整个问题刚刚解决,它是节点mssql包中的一个bug或其他东西。仅当您提供用户名和密码时,它才起作用。如果使用选项:{trustedConnection:true}
启用windows身份验证,则路由器永远无法登录。我不知道为什么会出现这种情况,但如果您只提供用户名和密码(我使用sa进行测试),那么它工作正常。调用是否可能等待MSSQL_MYDB.connect()
导致错误,因为它已经连接?@TKoL我从未调用控制器中的两个Offer.getOffersAll()
函数。我只叫它一次。。。因此,当我在我的路由器.get('/')
部分中尝试它时,我将注释掉测试函数。因此,不应该有两个等待MSSQL_MYDB_connect()代码>正在运行。我试图移动它:const DB_MYDB_Config={server:“localhost”,database:“MYDB”,选项:{trustedConnection:true};const MSSQL_MYDB=new MSSQL.ConnectionPool(DB_MYDB_Config)
进入我的offer.js文件,它仍然不起作用。它不再在全局范围内,因此应该可以正常工作?您是否将其移动到getOffersAll
函数内部?是-我在getOffersAll
函数内部和外部都尝试了它。获取与登录失败相同的错误。
(async function () {
var rsOffersAll = await Offer.getOffersAll();
console.dir(rsOffersAll); // works great! recordset rsOffersAll is printed to console
})();
router.get('/', async function(req, res) {
const MSSQL_MYDB = req.app.get('MSSQL_MYDB')
var rsOffersAll = await getOffersTest(MSSQL_MYDB );
console.dir(rsOffersAll);
res.render('index', { pagetitle: 'Homepage'}); // still never renders
});