当前位置: 首页 > 知识库问答 >
问题:

NodeJS在函数中的/catch似乎是在函数外部捕获代码

高和通
2023-03-14

我正在尝试构造这段代码,这样我就可以从多个地方调用getStudent。我正在尝试编写一些JSON例程。我正在尝试错误的第一回调模式。我不是因为这个错误而感到不安,而是因为这个错误被getstudent中的一个捕获器捕获了。

顺便说一句,我发现错误是做状态(200)而不是状态(0)。

我应该如何重新构造这些捕获,使它们不影响主代码?还是我完全误用了回调的概念?似乎“then/catch”是使用MSSQL处理异步的正确方法。

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

// config for your database
var config = {
    user: 'ReadOnlyUser1',
    password: 'whatever',
    server: 'localhost\\SQLEXPRESS', 
    database: 'StudentsOld' 
};

var lookupStudentId = 31; 


const sql = require('mssql');

var connPool = new sql.ConnectionPool(config);

function getStudent(studentId, callback) {
        console.log("Starting getStudent"); 
        nullResult = {}; 
        connPool.connect().
        then (function() {
            console.log('Connected - starting query'); 
            var request = new sql.Request(connPool); 
            var sqlQuery = 'select student_firstname, student_lastname from students where student_id = ' + studentId;  
            request.query(sqlQuery).
            then(function (recordSet) {
                    console.log('Query completed'); 
                    connPool.close(); 
                    console.log("recordSet="); 
                    console.dir(recordSet); 
                    callback(nullResult, recordSet); 
            }).catch(function (queryErr) {
                    console.log('Error in database query: ' + queryErr); 
                    callback('Error in db query: ' + queryErr, nullResult);  
                });
        }).catch(function (connErr) { 
                    console.log('Error in database connection: ' + connErr); 
                    callback('Error in db conn: ' + connErr, nullResult);  
                }); 
        console.log('fall thru 1'); 
}

function isEmptyObject(obj) {
  return !Object.keys(obj).length;
}

app.get('/student', function(request, response){
    console.log('Neal Test1'); 
    getStudent(lookupStudentId, function(err, result){
        console.log('Back from getStudent'); 
        if(!isEmptyObject(err)) {
            console.log("error400=" + err); 
            console.log("empty test=" + Object.keys(err).length); 
            response.status(400).send(err);
        }
        else 
        {
            console.log("result="); 
            console.dir(result); 
            console.log('about to send back status=0'); 
            response.status(0).send(result); 
        }
    })
    return;
});

app.listen(3000, function () {
    console.log('Express server is listening on port 3000');
});

我通过在浏览器中输入:http://localhost:3000/student来运行上述操作。

控制台输出为:

C:\Software\nodejs\myapp>node index.js
Express server is listening on port 3000
Neal Test1
Starting getStudent
fall thru 1
Connected - starting query
Query completed
recordSet=
{ recordsets: [ [ [Object] ] ],
  recordset:
   [ { student_firstname: 'Jonah                  ',
       student_lastname: 'Hill                    ' } ],
  output: {},
  rowsAffected: [ 1 ] }
Back from getStudent
result=
{ recordsets: [ [ [Object] ] ],
  recordset:
   [ { student_firstname: 'Jonah                  ',
       student_lastname: 'Hill                    ' } ],
  output: {},
  rowsAffected: [ 1 ] }
about to send back status=0
Error in database query: RangeError: Invalid status code: 0
Back from getStudent
error400=Error in db query: RangeError: Invalid status code: 0
empty test=53

修订1:

function getStudent(studentId) {
        console.log("Starting getStudent"); 
        recordset = {}; 
        connPool.connect().
        then (function() {
            console.log('Connected - starting query'); 
            var request = new sql.Request(connPool); 
            var sqlQuery = 'select student_firstname, student_lastname from students where student_id = ' + studentId;  
            request.query(sqlQuery).
            then(function (recordSet) {
                    console.log('Query completed'); 
                    connPool.close(); 
                    console.log("recordSet="); 
                    console.dir(recordSet); 
                    return recordset; 
            }).catch(function (queryErr) {
                    console.log('Error in database query: ' + queryErr); 
                    return queryErr; 
                });
        }).catch(function (connErr) { 
                    console.log('Error in database connection: ' + connErr); 
                    return connErr; 
                }); 
        console.log('fall thru 1'); 
}


app.get('/student', function(request, response){
    console.log('Neal Test1 - start app.get for /student'); 
    getStudent(lookupStudentId)
        .then (function(recordset)  {
            console.log('Back from getStudent,  recordSet='); 
            console.dir(recordSet); 
            response.status(200).send(recordset); 
        })
        .catch (function(err) {
            console.log("error400=" + err); 
            console.log("empty test=" + Object.keys(err).length); 
            response.status(400).send(err);
        })
    return;
});

修订版1的结果:

Express server is listening on port 3000
Neal Test1 - start app.get for /student
Starting getStudent
fall thru 1
TypeError: Cannot read property 'then' of undefined
    at C:\Software\nodejs\wisdomcalls\index.js:55:9
    at Layer.handle [as handle_request] (C:\Software\nodejs\wisdomcalls\node_modules\express\lib\router\layer.js:95:5)
    at next (C:\Software\nodejs\wisdomcalls\node_modules\express\lib\router\route.js:137:13)
    at Route.dispatch (C:\Software\nodejs\wisdomcalls\node_modules\express\lib\router\route.js:112:3)
    at Layer.handle [as handle_request] (C:\Software\nodejs\wisdomcalls\node_modules\express\lib\router\layer.js:95:5)
    at C:\Software\nodejs\wisdomcalls\node_modules\express\lib\router\index.js:281:22
    at Function.process_params (C:\Software\nodejs\wisdomcalls\node_modules\express\lib\router\index.js:335:12)
    at next (C:\Software\nodejs\wisdomcalls\node_modules\express\lib\router\index.js:275:10)
    at expressInit (C:\Software\nodejs\wisdomcalls\node_modules\express\lib\middleware\init.js:40:5)
    at Layer.handle [as handle_request] (C:\Software\nodejs\wisdomcalls\node_modules\express\lib\router\layer.js:95:5)
Connected - starting query
Query completed
recordSet=
{ recordsets: [ [ [Object] ] ],
  recordset:
   [ { student_firstname: 'Jonah                ',
       student_lastname: 'Hill                    ' } ],
  output: {},
  rowsAffected: [ 1 ] }

日志中,您可以看到主函数甚至在连接数据库之前就在运行。

修订版2:这似乎返回了连接而不是查询?请参阅console.log“未定义”。

function getStudent(studentId) {
        console.log("Starting getStudent"); 
        recordset = {}; 
        return connPool.connect()
        .then (function() {
            console.log('Connected - starting query'); 
            var request = new sql.Request(connPool); 
            var sqlQuery = 'select student_firstname, student_lastname from students where student_id = ' + studentId;  
            return request.query(sqlQuery)
            ;
            /*
            .then(function (recordSet) {
                    console.log('Query completed'); 
                    connPool.close(); 
                    console.log("recordSet="); 
                    console.dir(recordSet); 
                    //return recordset; 
            }).catch(function (queryErr) {
                    console.log('Error in DB query: ' + queryErr); 
                    //return queryErr; 
                });
        }).catch(function (connErr) { 
                    console.log('Error in DB connection: ' + connErr); 
                    //return connErr; 
             */
            }); 
        console.log('fall thru 1'); 
}

结果:

Connected - starting query
SQL Query = select student_firstname, student_lastname from students where student_id = 31
error400=ReferenceError: recordSet is not defined
empty test=0

共有2个答案

沈皓君
2023-03-14

您的回调概念是可以的,您还可以在getStudent函数中创建自己的promise并返回它,这将使您的代码更易读。问题具有response.status(0).send(结果);xhr调用不存在这样的状态,否则将生成错误。在这里,您可以通过它们的全局可接受用法获得一些有用的状态http://www.restapitutorial.com/httpstatuscodes.html

宿嘉庆
2023-03-14

你似乎把承诺和回调混为一谈,这让我觉得一切都变得更加混乱。使用promise的一般模式是返回它们,然后调用then,这将给出解析的promise的返回值。记住then()也返回一个承诺,这就是您如何链接它们的方法。

您可以只从您的函数返回connPool.connect()返回的承诺。然后被调用者可以对其调用then()catch()。错误将浮动到最后的catch()

我没有sql的连接,所以我无法测试它,但我的想法是这样的(为了清晰起见,简化了):

const sql = require('mssql');

var connPool = new sql.ConnectionPool(config);

function getStudent(studentId) {
        nullResult = {}; 
        return connPool.connect() //return the promise from your function
        .then (function() {
            console.log('Connected - starting query'); 
            var request = new sql.Request(connPool); 
            var sqlQuery = 'select student_firstname, student_lastname from students where student_id = ' + studentId;  
            connPool.close(); 
            return request.query(sqlQuery) // returns the promise from request
        })      

}


app.get('/student', function(request, response){
    getStudent(lookupStudentId)
    .then(function(recordSet){
        // recordSet should be promise resolution of request.query
    })
    .catch(function(err) {
        // catch errors here
    })
})

下面是一个成对的示例,它通过一个简单的异步promise mock来帮助展示promise链接的作用,该promise mock返回您发送的内容。您可以取消throw()的注释,以查看错误是如何冒出的:

function getStudent(val) {
        return async(val)
        .then (function(v) {
           // console.log("In outer with, ", v)
            return async("processes value: " + v)
        })
        .then(function (value) {
            //console.log("Inside value got: ", value)
            //throw("Some Error")
            return async("processed again: " + value)
        })
}

getStudent("Start_Value")
.then((value) => {
    console.log("Final return: ",value)
})
.catch((err) => console.log("whoops err: ", err))

function async(p) {
    return new Promise((resolve, reject) => {
        //throw("async error")
        setTimeout(() => {
            resolve( "FROM ASYNC: " + p )
        }, 500)
    })
}
 类似资料:
  • 从数据库中提取博客。 为什么这里的blogContent在函数的上下文中是全局的,而我们正在内部更改它,所以它应该返回值,有人能解释为什么会这样吗? 有没有不使用promise/async/await的方法>>>有人给了我答案 我如何从异步调用返回响应? 但这一点我不知道,最主要的是我不知道Ajax。

  • 问题内容: 我正在努力推动 作为新的ID和json字符串的值。但是它给出了以下错误 提前谢谢您的回复 问题答案: 要使用Array的push函数,您的var必须是一个Array。 更改为以下内容: 包含的数组项将是typeof对象,您可以执行以下操作: 注意:请保持一致。在我的示例中,一个数组包含对象属性,而另一个仅包含对象属性。如果我使用或进行迭代,那么我将无法始终检查一个属性,因为我的示例包含

  • 我在控制台中得到以下错误:。 也许问题出在不推荐的JSXTransformer上(https://facebook.github.io/react/blog/2015/06/12/deprecating-jstransform-and-react-tools.html)。建议使用Babel代替(在我的例子中,使用Babel!view/todolist代替jsx!view/todolist)。我对此

  • 问题内容: 我有一个像这样的简单循环: 控制器中有一个功能。 据我所知,Angular将首先渲染视图并用数字替换插值,然后在单击事件时将评估字符串。 在这种情况下,完全可以得到预期的结果,即:但是……它什么也没做。 当然,我可以编写代码以从数组甚至DOM中获取代码,但这似乎不像Angular那样。 那么,如何在循环内向指令添加动态内容呢? 问题答案: 代替 做这个: 请看这个小提琴: http:/

  • 问题内容: 我正在考虑在以后的所有Web应用程序中使用PDO。当前(使用到目前为止我从中学到的知识),我站点中用于处理数据库连接的内容是一个Singleton类,如下所示: 另一个文件(functions.php)具有特定于内容的功能,看起来像这样: 这意味着我必须重复所有功能。 我的问题是: 我应该如何提高效率?(例如,不必在所有功能中都重复执行,但仍然能够在每个功能上返回不同的“失败消息”)

  • 我们正在尝试将我们的 zip 微服务从节点js Express 中的常规应用程序迁移到与 AWS Lambda 集成的 AWS API 网关。 我们当前的应用程序向我们的API发送请求,获取附件列表,然后访问这些附件并将其内容以zip存档的形式传回给用户。它看起来像这样: 除了必须将内容从Lambda函数中流出来的部分,我已经设法完成了所有的工作。< br >我认为可能的解决方案之一是使用aws-