最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

在单独的文件nodejs中调用mssql模块连接时出现问题

网站源码admin27浏览0评论

在单独的文件nodejs中调用mssql模块连接时出现问题

在单独的文件nodejs中调用mssql模块连接时出现问题

我使用 mssql 包的经历很糟糕,该包将连接作为承诺返回,以便能够使用像

query
这样的方法,我应该首先等待连接,然后使用它类似

const sql = require('mssql')
const sqlConfig = {
  user: process.env.DB_USER,
  password: process.env.DB_PWD,
  database: process.env.DB_NAME,
  server: 'localhost',
  pool: {
    max: 10,
    min: 0,
    idleTimeoutMillis: 30000
  },
  options: {
    encrypt: true, // for azure
    trustServerCertificate: false // change to true for local dev / self-signed certs
  }
}
sql.connect(config).then(async pool => {
  const query = await pool.query`select * from table_name`;
  console.log(query)
})

但是我当然不会在单个文件中使用该连接,我想将其导出以在不同的路由文件中使用它,因此对于这种情况,我找到了 2 个解决方案,它们不是最佳实践,也不是我的良好编程经验包文档中首先介绍了意见 首先连接到 SQL 服务器,然后运行节点服务器并在应用程序本地附加连接,我认为这确实是一个非常糟糕的解决方案,它会停止数据库连接上的整个服务器,如果连接失败,这意味着整个服务器获胜了怎么办?即使有不需要数据库连接的静态文件也无法启动,用户将无法再访问它,这是提供的解决方案

const express = require('express')
const sql = require('mssql')
const config  = {/*...*/}
//instantiate a connection pool
const appPool = new sql.ConnectionPool(config)
//require route handlers and use the same connection pool everywhere
const route1 = require('./routes/route1')
const app = express()
app.get('/path', route1)

//connect the pool and start the web server when done
appPool.connect().then(function(pool) {
  app.locals.db = pool;
  const server = app.listen(3000, function () {
    const host = server.address().address
    const port = server.address().port
    console.log('Example app listening at http://%s:%s', host, port)
  })
}).catch(function(err) {
  console.error('Error creating connection pool', err)
});

因此要访问它,我将使用类似以下内容

const express = require('express');
const router = express.Router();

router.get('/', async (req, res, next) => {
  req.app.locals.db.query('SELECT TOP 10 * FROM table_name', function(err, recordset) {
    if (err) {
      console.error(err)
      res.status(500).send('SERVER ERROR')
      return
    }
    res.status(200).json({ message: 'success' })
  })
})

这是我发现的第一个解决方案,第二个解决方案是导出连接,每次我想使用类似

query
的方法时,我无法直接调用它,我应该重复一个静态步骤,谁是
const pool = await connection; const query = await connection.query('my query string')
事实上,该解决方案比第一个更好,但每次我认为这不是一个好的程序员体验时,我都应该重复一个步骤,这是代码示例

const sql = require('mssql');
const { normalizePort } = require('./handlers');
const {
  SQL_SERVER_USER,
  SQL_SERVER_PASSWORD,
  SQL_SERVER,
  SQL_SERVER_DATABASE,
  SQL_SERVER_PORT
} = require('./configurations/appConfig');

const config = {
  user: SQL_SERVER_USER,
  password: SQL_SERVER_PASSWORD,
  database: SQL_SERVER_DATABASE,
  server: SQL_SERVER,
  port: normalizePort(SQL_SERVER_PORT),
  pool: {
    max: 10,
    min: 0,
    idleTimeoutMillis: 30000
  },
  options: {
    encrypt: true,
    trustServerCertificate: true, // change to true for local dev / self-signed certs
  }
}
const connection = sql.connect(sqlConfig)

module.exports = connection;

假设上面代码的文件名是

db.js
,然后在一个名为
production.js
的路由文件中有3条路由,所以让我们导入上面的连接并在该路由中使用它

const express = require('express');
const router = express.Router();
const connection = require('../db.js')


router.get('/products', async (req, res, next) => {
  const pool = await connection;
  const query = await pool.query`select * from products`;
  res.setHeader("Content-Type", 'application/json; charset=utf-8');
  res.status(200).send(JSON.stringify(query, null, 4));
});

router.post('/brands', async (req, res, next) => {
  const pool = await connection;
  const query = await pool.query`select * from brands`;
  res.setHeader("Content-Type", 'application/json; charset=utf-8');
  res.status(200).send(JSON.stringify(query, null, 4));
});

router.post('/categories', async (req, res, next) => {
  const pool = await connection;
  const query = await pool.query`select * from categories`;
  res.setHeader("Content-Type", 'application/json; charset=utf-8');
  res.status(200).send(JSON.stringify(query, null, 4));
});

module.exports = router

在上面的每个路线的示例中,我应该调用

const pool = await connection;
重复的代码,我认为这不是最佳实践,也不是良好的程序员体验,我正在寻找更好的解决方案,我可以在其中导入连接并直接访问
 query
无需额外步骤的方法。

回答如下:

在经过一番搜索后,您似乎很难使用 mssql 模块,我想如果我有一个返回对象的函数,并且该对象包含一个名为

query
的函数,但只需等待
query
函数已经不存在并且该函数不会返回它,您必须等待一段时间,直到加载包含
query
方法的对象,然后您可以调用
query
方法并执行它,因此,如果您调用该函数点查询,它将是未定义的,如果您调用它,你会得到一个漂亮的错误,谁是
TypeError: function_name(...).query is not a function
来解决这个问题,你可以使用
Proxy
对象,这样当你的函数调用时,它将直接从该代理对象返回一个新的
Proxy
对象,你可以访问被调用的方法名称然后返回一个函数来访问参数,类似于下面的基本示例

const obj = {
  sum: n => n + 2,
}

function proxyfire() {
  return new Proxy({}, {
    //in the following property param you will receive the invoked method name
    get: function(target, property) {
      console.log(property);
      //now let's get the called method arguments
      return function() {
        console.log(arguments);
        if(obj[property]) {
          return obj[property](...arguments)
        }
        return () => null
      }
    }
  })
}

const sum = proxyfire().sum(1)
console.log(sum)//result is 3

在上面的示例中,我们调用了

sum
方法,该方法不包含在返回结果中,但它已经存在于
obj
中,因此当调用
proxifire().sum(1)
时,
proxifire
方法将充当中间件或桥梁之间的桥梁
obj
和您调用的方法,您可以通过返回一个新函数来访问被调用的方法名称及其参数,我们可以使用上面的示例来处理多次重复
await connection
的问题让我们看一下并使用您的一个然后在示例中添加
proxyfire
,它将作为直接调用和等待之间的桥梁,直到连接完成并准备好调用
query
方法

const sql = require('mssql');
const { normalizePort } = require('./handlers');
const {
  SQL_SERVER_USER,
  SQL_SERVER_PASSWORD,
  SQL_SERVER,
  SQL_SERVER_DATABASE,
  SQL_SERVER_PORT
} = require('./configurations/appConfig');

const sqlConfig = {
  user: SQL_SERVER_USER,
  password: SQL_SERVER_PASSWORD,
  database: SQL_SERVER_DATABASE,
  server: SQL_SERVER,
  port: normalizePort(SQL_SERVER_PORT),
  pool: {
    max: 10,
    min: 0,
    idleTimeoutMillis: 30000
  },
  options: {
    encrypt: true,
    trustServerCertificate: true, // change to true for local dev / self-signed certs
  }
}

const connection = sql.connect(sqlConfig);


function proxyfire() {
  return new Proxy({}, {
    //getting the called property
    get: function (target, prop) {
      //let's get the called function arguments to send it
      return function () {
        return connection.then(poolConnection => {
          // Check if the method exists in the object
          if (poolConnection[prop]) {
            // Return a function that invokes the method with the provided arguments
            return poolConnection[prop](...arguments);
          }
          //method unavailable
          return () => null;
        });
      }
    }
  });
}

module.exports = proxyfire;

上面的文件名为

db.js
,我们想在
production.js
路线中导入并使用它,所以让我们使用它吧

const express = require('express');
const router = express.Router();
const proxyfire = require('../db.js');
const pool = proxyfire()


router.get('/products', async (req, res, next) => {
  const query = await pool.query`select * from products`;
  res.setHeader("Content-Type", 'application/json; charset=utf-8');
  res.status(200).send(JSON.stringify(query, null, 4));
});

router.post('/brands', async (req, res, next) => {
  const query = await pool.query`select * from brands`;
  res.setHeader("Content-Type", 'application/json; charset=utf-8');
  res.status(200).send(JSON.stringify(query, null, 4));
});

router.post('/categories', async (req, res, next) => {
  const query = await pool.query`select * from categories`;
  res.setHeader("Content-Type", 'application/json; charset=utf-8');
  res.status(200).send(JSON.stringify(query, null, 4));
});

module.exports = router

如您所见,您可以直接调用

query
方法并接收查询响应,您只需调用路线顶部的
proxifire
方法,然后按照您的意愿使用它

这是一个完整的使用示例

const sql = require('mssql');
const { normalizePort } = require('../handlers/handlers');
const {
  SQL_SERVER_USER,
  SQL_SERVER_PASSWORD,
  SQL_SERVER,
  SQL_SERVER_DATABASE,
  SQL_SERVER_PORT
} = require('../configurations/appConfig');

const config = {
  user: SQL_SERVER_USER,
  password: SQL_SERVER_PASSWORD,
  database: SQL_SERVER_DATABASE,
  server: SQL_SERVER,
  port: normalizePort(SQL_SERVER_PORT),
  pool: {
    max: 10,
    min: 0,
    idleTimeoutMillis: 30000
  },
  options: {
    encrypt: true,
    trustServerCertificate: true, // change to true for local dev / self-signed certs
  }
}

const connection = sql.connect(config);

module.exports = (function () {
  return new Proxy({}, {
    //getting the called property
    get: function (target, prop) {
      //let's get the called function arguments to send it
      return async function () {
        const poolConnection = await connection;
        // Check if the method exists in the object
        if (poolConnection[prop]) {
          // Return a function that invokes the method with the provided arguments
          return poolConnection[prop](...arguments);
        }
        //method unavailable
        return () => null;
      }
    }
  });
})();

通过这个示例,您甚至不需要在路线模块顶部调用

proxyfire
只需需要并使用它

const express = require('express');
const router = express.Router();
const pool = require('../db.js');


router.get('/products', async (req, res, next) => {
  const query = await pool.query`select * from products`;
  res.setHeader("Content-Type", 'application/json; charset=utf-8');
  res.status(200).send(JSON.stringify(query, null, 4));
});

router.post('/brands', async (req, res, next) => {
  const query = await pool.query`select * from brands`;
  res.setHeader("Content-Type", 'application/json; charset=utf-8');
  res.status(200).send(JSON.stringify(query, null, 4));
});

router.post('/categories', async (req, res, next) => {
  const query = await pool.query`select * from categories`;
  res.setHeader("Content-Type", 'application/json; charset=utf-8');
  res.status(200).send(JSON.stringify(query, null, 4));
});

module.exports = router

发布评论

评论列表(0)

  1. 暂无评论