簡體   English   中英

NodeJS、Express、MSSQL - 如何在打印到控制台之前等待 MSSQL 池連接並返回查詢結果

[英]NodeJS, Express, MSSQL - How do I wait for MSSQL pool to connect and return query result before printing to console

Node Version -                 16.1.0
Microsoft SQL Server 2008 -    10.50.2550.0
SQL Server Management Studio - 15.0.18358.0
Windows 10 Pro Edition -       2004
OS Build ^ -                   19041.572

Project Architecture:
root
|- <node_modules>
|- index.js
|- databaseStuff.js
|- test.js
|- package.json

重要說明,我必須使用以下命令運行我的應用程序: node --tls-min-v1.0 index.js

我正在制作 API 從 GitLab webhook 獲取信息並使用 NodeJS、Express 和 MSSQL 寫入表。 我將從存儲過程中執行各種讀/寫操作,但第一步是執行一個簡單的查詢。 我想將查詢結果作為 HTTP 響應發送。

我遇到問題的部分是圍繞數據庫連接計時查詢。

我收到的錯誤包含 ConnectionError 代碼“ENOTOPEN”(請參閱 error_console_output)

// error_console_output

Server is running..
Promise { <pending> }
Connected to DB
TypeError: Cannot read property 'on' of undefined
    at \root\node_modules\mssql\lib\tedious\request.js:428:
20
    at \root\node_modules\mssql\lib\base\connection-pool.js
:289:41
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at runNextTicks (node:internal/process/task_queues:65:3)
    at processImmediate (node:internal/timers:437:9)
\root\node_modules\mssql\lib\base\connection-pool.js:298
      return shared.Promise.reject(new ConnectionError('Connection not yet open.
', 'ENOTOPEN'))
                                   ^

ConnectionError: Connection not yet open.
    at ConnectionPool._acquire (\root\node_modules\mssql\li
b\base\connection-pool.js:298:36)
    at ConnectionPool.acquire (\root\node_modules\mssql\lib
\base\connection-pool.js:284:56)
    at Immediate.<anonymous> (\root\node_modules\mssql\lib\
tedious\request.js:409:19)
    at processImmediate (node:internal/timers:464:21) {
  code: 'ENOTOPEN'
}

我的一部分想知道我的 SQL 服務器版本是否與 MSSQL 不兼容,或者我只是沒有正確編寫連接。

// index.js

var db = require('./databaseStuff')

var express = require('express');
var app = express();

app.get('/', function(req, res) {
  var result = db.execute();
  console.log(result);
})

var server = app.listen(8080, function () {
    console.log('Server is running..');
});

// databaseStuff.js

var sql = require("mssql");

var config = {
    user: 'user',
    password: 'password',
    server: 'server',
    database: 'DBname',
    options: {
      encrypt: true,
      trustServerCertificate: true
    }
};

var sqlQuery = "select * from Games";

async function connectDB()
{
  const pool = new sql.ConnectionPool(config);

  try
  {
    await pool.connect();
    console.log('Connected to DB');
    return pool;
  }
  catch (err)
  {
    console.log('Failed to connect to DB', err);

    return err;
  }
}

async function getGames() {
  const DB = await connectDB();

  try {
    const result = await DB.request().query(sqlQuery, function (err, res) {
      if (err) console.log(err);
      else console.log(res);
    });

    return result.recordset;
  }
  catch (err)
  {
    console.log('Error querying DB', err);

    return err;
  }

  finally
  {
    DB.close();
  }
}

async function execute()
{
  let result = await getGames();

  return result;
}

module.exports = {
  execute
};

// package.json

{
  "name": "root",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1",
    "msnodesqlv8": "^2.1.0",
    "mssql": "^7.1.0",
    "tedious": "^6.2.0"
  }
}

在我試圖解構它之前,我有一些工作。 test.js 將等待 MSSQL 查詢返回結果。 我會使用它,但我想讓我的代碼與主要的 class 分開。 請注意,test.js 將發送 SQL 查詢結果作為響應正文,我想保留此行為。 (見預期結果)。

// test.js

var express = require('express');
var app = express();
var server = app.listen(8080, function () {
    console.log('Server is running..');
    var sql = require("mssql");
    // config for your database
    var config = {
        user: 'user',
        password: 'password',
        server: 'server',
        database: 'DBname',
        options: {
          encrypt: true,
          trustServerCertificate: true
        }
    };
    // connect to your database
    sql.connect(config, function (err) {
        if(err)
        {
            console.log("CONNECTION: " + err);
            return;
        }
        console.log("Connected!!");
        // create Request object
        var request = new sql.Request();
        // query to the database and get the records
        request.query('select * from Games', function (err, recordset) {
            if (err)
            {
                 console.log("QUERY: " + err);
            }
            // send records as a response
            console.log(recordset);
            //res.send(recordset);
        });
    });
});

// 預期成績

{
  recordsets: [ [ [Object] ] ],
  recordset: [ { ID: 1, Name: 'GameName' } ],
  output: {},
  rowsAffected: [ 1 ]
}

編輯:

app.get('/', async function(req, res) {
  try
  {
    var result = await db.execute();
    console.log(result);
  }
  catch (error)
  {
    console.log(error);
  }
})

上述更改可防止“console.log(result)”在返回結果之前觸發。 但是,我仍然遇到來自 error_console_output 的相同 ConnectionError。

我想出了以防萬一有人遇到這個問題。 如需進一步參考,請查看此

我的問題是由於沒有正確創建到我的數據庫的連接。 我遵循了 mssql 文檔的連接池部分(之前鏈接)。

此方法確保在繼續請求之前已創建並保護連接

// index.js

var db = require('./databaseStuff')

var express = require('express');

var app = express();

var server = app.listen(8080, function () {
    var port = server.address().port;
    console.log("App now running on port", port);
});

app.get('/', async function(req, res) {
  let result = await db.execute();
  res.send(result);
  res.status(200).end();
  console.log(result);
})

// databaseStuff.js

var sql = require("mssql");

// config for your database
var config = {
    user: 'user',
    password: 'password',
    server: 'server',
    database: 'DB',
    options: {
      encrypt: true,
      trustServerCertificate: true
    }
};

// async/await style
const pool1 = new sql.ConnectionPool(config);
const pool1Connect = pool1.connect();

pool1.on('error', err => {
  console.log(err);
})

var sqlQuery = "select * from Games";

async function getGames() {
  // ensure pool has been created
  await pool1Connect;

  try
  {
    const request = pool1.request();
    const result = await request.query(sqlQuery);

    return result.recordset;
  }
  catch (err)
  {
    console.error('SQL Error', err);
  }
}

async function execute()
{
  return await getGames();
}

module.exports = {
  execute
};

// output

App now running on port 8080
[ { ID: 1, Name: 'GameName' } ]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM