Het is 3 jaar geleden dat ik de vraag heb gesteld en beantwoord. Sindsdien zijn er een aantal dingen veranderd. Hier is de nieuwe oplossing op basis van ES6, mssql 4 en Express 4 die ik vandaag zou aanraden.
Twee belangrijke elementen spelen hier een rol.
- Modules worden in de cache opgeslagen nadat ze voor het eerst zijn geladen. Dit betekent dat elke aanroep naar required('./db') exact hetzelfde object zal retourneren. De eerste vereiste van db.js zal dat bestand uitvoeren en de belofte maken en exporteren. De tweede vereiste van db.js zal DIEzelfde belofte retourneren zonder het bestand uit te voeren. En het is die belofte die met het zwembad zal worden opgelost.
- Een belofte kan dan weer worden nagekomen. En als het eerder is opgelost, wordt het meteen weer opgelost met alles wat het de eerste keer heeft opgelost, namelijk de pool.
In server.js
const express = require('express')
// require route handlers.
// they will all include the same connection pool
const set1Router = require('./routes/set1')
const set2Router = require('./routes/set2')
// generic express stuff
const app = express()
// ...
app.use('/set1', set1Router)
app.use('/set2', set2Router)
// No need to connect the pool
// Just start the web server
const server = app.listen(process.env.PORT || 3000, () => {
const host = server.address().address
const port = server.address().port
console.log(`Example app listening at http://${host}:${port}`)
})
In db.js
const sql = require('mssql')
const config = {/*...*/}
const poolPromise = new sql.ConnectionPool(config)
.connect()
.then(pool => {
console.log('Connected to MSSQL')
return pool
})
.catch(err => console.log('Database Connection Failed! Bad Config: ', err))
module.exports = {
sql, poolPromise
}
In routes/set1.js
en routes/set2.js
const express = require('express')
const router = express.Router()
const { poolPromise } = require('./db')
router.get('/', async (req, res) => {
try {
const pool = await poolPromise
const result = await pool.request()
.input('input_parameter', sql.Int, req.query.input_parameter)
.query('select * from mytable where id = @input_parameter')
res.json(result.recordset)
} catch (err) {
res.status(500)
res.send(err.message)
}
})
module.exports = router
Samenvattend
Je krijgt altijd dezelfde belofte vanwege module-caching en die belofte zal, keer op keer, worden opgelost met de pool die het de eerste keer heeft opgelost. Elk routerbestand gebruikt dus dezelfde pool.
Tussen haakjes:er zijn eenvoudigere manieren om de try-catch in de expresroute uit te voeren die ik in dit antwoord niet zal behandelen. Lees er hier meer over:https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016
De oude oplossing
Dit is de oplossing die ik 3 jaar geleden heb gepost, omdat ik dacht dat ik een antwoord had dat de moeite waard was om te delen en ik nergens een gedocumenteerde oplossing kon vinden. Ook in een paar nummers (#118, #164, #165) op node-mssql wordt dit onderwerp besproken.
In server.js
var express = require('express');
var sql = require('mssql');
var config = {/*...*/};
//instantiate a connection pool
var cp = new sql.Connection(config); //cp = connection pool
//require route handlers and use the same connection pool everywhere
var set1 = require('./routes/set1')(cp);
var set2 = require('./routes/set2')(cp);
//generic express stuff
var app = express();
//...
app.get('/path1', set1.get);
app.get('/path2', set2.get);
//connect the pool and start the web server when done
cp.connect().then(function() {
console.log('Connection pool open for duty');
var server = app.listen(3000, function () {
var host = server.address().address;
var 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);
});
In routes/set1.js
var sql = require('mssql');
module.exports = function(cp) {
var me = {
get: function(req, res, next) {
var request = new sql.Request(cp);
request.query('select * from test', function(err, recordset) {
if (err) {
console.error(err);
res.status(500).send(err.message);
return;
}
res.status(200).json(recordset);
});
}
};
return me;
};