NodeJS然后/捕获一个函数似乎是捕获function外的代码

我试图构造这个代码,所以我可以从多个地方调用getStudent。 我正在尝试编写一些JSON例程。 我正在尝试第一个callback模式。 这不是那么多的错误让我感到不安,而是错误被getStudent中的一个捕获。

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

我应该如何重组这样的渔获量,以便它们不影响主代码? 还是我完全滥用callback概念? 看起来像“then / catch”是处理与mssqlasynchronous的正确方法。

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'); }); 

我在浏览器中input: 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“undefined”。

 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 

你似乎混合了Promises和Callbacks,这种方式让所有的事情都变得混乱起来,这对我来说是需要的。 承诺的一般模式是返回它们,然后再打电话,这将给你从解决的承诺的回报价值。 请记住, then()也会返回一个承诺,那就是如何链接它们。

你可以直接从你的函数中返回connPool.connect()返回的Promise。 然后被调用者可以调用then()catch() 。 错误将浮动到最后的catch()

我没有sql的连接,所以我不能testing这个,但我的头顶上的想法是这样的(为了清晰起见,简化):

 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 }) }) 

下面是一个配对的例子,它通过一个简单的asynchronouspromise模拟来帮助显示承诺链接,并返回您发送的内容。 您可以取消注释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) }) } 

你的callback概念是可以的,你也可以在getStudent函数中创build自己的承诺并返回它,这将使你的代码更具可读性。 问题与response.status(0).send(result); xhr调用不存在这种状态,否则会产生错误。 在这里,你可以得到一些有用的状态与他们的全球可接受的用法http://www.restapitutorial.com/httpstatuscodes.html