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



我正在尝试构建此代码,以便我可以从多个地方调用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:Softwarenodejsmyapp>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:Softwarenodejswisdomcallsindex.js:55:9
at Layer.handle [as handle_request] (C:Softwarenodejswisdomcallsnode_modulesexpresslibrouterlayer.js:95:5)
at next (C:Softwarenodejswisdomcallsnode_modulesexpresslibrouterroute.js:137:13)
at Route.dispatch (C:Softwarenodejswisdomcallsnode_modulesexpresslibrouterroute.js:112:3)
at Layer.handle [as handle_request] (C:Softwarenodejswisdomcallsnode_modulesexpresslibrouterlayer.js:95:5)
at C:Softwarenodejswisdomcallsnode_modulesexpresslibrouterindex.js:281:22
at Function.process_params (C:Softwarenodejswisdomcallsnode_modulesexpresslibrouterindex.js:335:12)
at next (C:Softwarenodejswisdomcallsnode_modulesexpresslibrouterindex.js:275:10)
at expressInit (C:Softwarenodejswisdomcallsnode_modulesexpresslibmiddlewareinit.js:40:5)
at Layer.handle [as handle_request] (C:Softwarenodejswisdomcallsnode_modulesexpresslibrouterlayer.js:95:5)
Connected - starting query
Query completed
recordSet=
{ recordsets: [ [ [Object] ] ],
recordset:
[ { student_firstname: 'Jonah                ',
student_lastname: 'Hill                    ' } ],
output: {},
rowsAffected: [ 1 ] }

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

修订版 2: 这似乎返回了连接而不是查询?请参阅控制台.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

您似乎正在混合承诺和回调,这使我需要的一切变得更加混乱。promise的一般模式是返回它们,然后调用then这将为你提供已解析的承诺的返回值。请记住,then()也会返回一个承诺,这就是您可以链接它们的方式。

你可以只从函数中返回connPool.connect()返回的 Promise。然后被调用者可以调用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
})
})

下面是一个配对示例,它有助于显示承诺链接的实际操作,其中包含一个简单的异步承诺模拟,该模拟返回您发送的内容。您可以取消注释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)
})
}

你的回调概念是可以的,你也可以在getStudent函数中创建自己的承诺并返回它,这将使你的代码更具可读性。问题在于响应状态(0(.send(result(;XHR 调用不存在此类状态,否则将生成错误。在这里,您可以通过其全局可接受的使用 http://www.restapitutorial.com/httpstatuscodes.html 获得一些有用的状态

最新更新