为什么异步函数在控制器的get()处理函数中不起作用?

我正在使用带有mssql npm package的Node and Express来连接到SQL Server数据库。我在app.js文件中执行此操作,该文件设置了一个global变量来为数据库创建一个connectionPool,如下所示(为简便起见,我省略了一些样板内容):

const mssql = require('mssql/msnodesqlv8'); // needs to use msnodesqlv8 driver for Windows Authentication to work
const express = require('express');
const app = express();

const DB_MYDB_Config = {
    server: "localhost",database: "MYDB",options: {
        trustedconnection: true // Windows auth enabled hence no username/password required
    }
};

global.MSSQL_MYDB = new mssql.ConnectionPool(DB_MYDB_Config); //connectionPool available to whole app

我有一个名为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,它实际上并不能正常工作(用注释解释):

    var router = require('express').Router();
    const Offer = require('../models/offer'); // the `offer.js` file

    /* the function below works perfectly */
    (async function () {
      var rsOffersAll = await Offer.getOffersAll();
      console.dir(rsOffersAll); // works great! recordset rsOffersAll is printed to console
    })();

    /* this is where it goes wrong even after commenting out the test function above */
    router.get('/',async function(req,res) {
     var rsOffersAll = await Offer.getOffersAll(); // this just hangs and eventually I get a login failed error for SQL Server. 
      console.dir(rsOffersAll);
      res.render('index',{ pagetitle: 'Homepage'}); // never renders
    });

module.exports = router;

我的问题是,为什么等待async function()的结果的第一个Offer.getOffersAll()不会失败,但是放置在router.get('/')处理程序中的同一个异步函数会因登录错误而失败?如果我从var rsOffersAll = await Offer.getOffersAll();处理程序中删除了router.get('/'),则页面将呈现,但是我当然没有数据要传递给它。

即使我将测试函数的值存储在变量中并尝试将其放在router.get()处理程序中,也会发生完全相同的事情:

async function getOffersTest() {
          return await Offer.getOffersAll();
        }

router.get('/',res) {
         var rsOffersAll = await getOffersTest(); // still breaks
          console.dir(rsOffersAll);
          res.render('index',{ pagetitle: 'Homepage'}); // still never renders
        });

我的最终问题是如何解决此问题,使其以应有的方式工作:访问主页时,路由器等待数据从数据库中返回,然后将其传递给视图或是否可以打印到控制台?

qyrwj 回答:为什么异步函数在控制器的get()处理函数中不起作用?

由于此行global.MSSQL_MYDB = new mssql.ConnectionPool(DB_MYDB_Config);

当您在路由器外部执行此代码时,

(async function () {
     var rsOffersAll = await Offer.getOffersAll();
     console.dir(rsOffersAll); // works great! recordset rsOffersAll is printed to console
  })();

getOffersAll可以访问全局变量,     并且您可以在第await MSSQL_MYDB.connect(); //行中与db成功连接

但是对于路由器,全局作用域是当前的module.exports对象,而不是全局对象。

解决方案

您可以像这样在应用中设置MSSQL_MYDB

app.set('MSSQL_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包中的错误或其他内容。仅当您提供用户名和密码时,它才有效。如果您使用options: {trustedConnection: true }启用Windows身份验证,则路由器将永远无法登录。我不知道为什么会这样,但是如果您仅提供用户名和密码(我使用sa进行测试),则它将工作正常。

本文链接:https://www.f2er.com/3080604.html

大家都在问