0

我创建了一个 node.js Web 应用程序。目前我正在为数据库使用 MSSQL。我添加了node-mssql包。我在一个名为sql.js的单独文件中创建了函数来执行相应的 SQL 函数。controller.js使用await 关键字调用它们。当我一次发出一个请求时我没有错误,但是如果两个请求大约在同一时间出现,我会收到以下错误。

(节点:136648)UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝 id:1):ReferenceError:未定义错误
(节点:136648)[DEP0018] DeprecationWarning:不推荐使用未处理的承诺拒绝。将来,未处理的 Promise 拒绝将使用非零退出代码终止 Node.js 进程。

我认为我与连接有关,我使用的是全局连接,但我调试了我的controller.js并看到该池已定义,所以我不确定是什么导致了问题。

SQL.js

const sql = require('mssql'); 
const config = {
    user: 'admin',
    password: 'linux',
    server: '11.222.33.44',
    database: 'master'
}
const pool = new sql.ConnectionPool(config); 
pool.on('error', err => {
    if (err) {
        console.log('sql errors', err);
    }
    if (!err) {
        pool.connect();
    }
});
module.exports.getUsers = async() => {
    // const pool = await sql.connect(config);
    try{
        const result  = await pool.request()
            .query(`SELECT * FROM master.dbo.users ORDER BY user_id`)
        // sql.close();
        return result.recordset; 
    }catch(err){
        throw error; 
    }
}
module.exports.getProducts = async() => {
    // const pool = await sql.connect(config);
    try{
        const result  = await pool.request()
            .query(`SELECT * FROM master.dbo.products ORDER BY product_zip`)
        // sql.close();
        return result.recordset; 
    }catch(err){
        throw error; 
    }
}

控制器.js

const express = require('express');
const {getInfo, getUsers, getProducts} = require('../lib/sql');
const router = express.Router();

...

/// Get Users
router.get('/controller/getUsers', async(req, res, next) => {
    console.log('get: /controller/getUsers'); 
    const users = await getUsers(); 
    res.status(200).json(users);   
});
/// Get Products
router.get('/controller/getProducts', async(req, res, next) => {
    console.log('get: /controller/getProducts'); 
    const products = await getProducts(); 
    res.status(200).json(products);
});
module.exports = router;
4

1 回答 1

4

router.get您的各种回调中没有错误处理,并且router.get不会对您传递给它的函数的返回值做任何事情,所以如果您传递一个async函数,函数返回的承诺将不会被处理,对于被拒绝的承诺,这是一个未处理的错误。因此出现错误消息。

相反:您必须处理错误。例如:

router.get('/controller/getUsers', async(req, res, next) => {
    try {
        console.log('get: /controller/getUsers'); 
        const users = await getUsers(); 
        res.status(200).json(templates);
    } catch (e) {
        res.status(500).send(/*...*/);
    }
});

这仍然返回一个从未处理过的承诺,但至少它永远不会拒绝(假设catch代码中没有任何失败)。

如果您有一种常见的返回错误的方式,您可能希望给自己一个包装函数router.get(等等)来处理来自回调的错误,以便很好地集中。

例如:

const asyncRouterGet = (route, handler) => {
    return router.get(route, (req, res, next) => {
        handler(req, res, next)
        .catch(err => {
            // Common error handling here
            res.status(500).send(/*...*/);
        });
    });
};

然后

asyncRouterGet('/controller/getUsers', async(req, res, next) => {
    console.log('get: /controller/getUsers'); 
    const users = await getUsers(); 
    res.status(200).json(templates);
});

...因为您知道拒绝将由asyncRouterGet生成的回调自动处理。


显然,不要这样做:

try {
    // ...
}
catch (err) {
    throw error;
}

error没有在您引用的代码中的任何地方定义,并且

try {
    // ...
}
catch (err) {
    throw err;
}

将毫无意义;如果您要重新抛出而不做任何其他事情,只需将try/关闭即可。catch

于 2018-02-13T15:40:37.063 回答