2017-07-28 16 views
1

我想这种结构的代码,所以我可以从多个地方调用getStudent以外的地方捕捉代码。我正在尝试编写一些JSON例程。我正在尝试第一个回调模式。这不是错误太多而让我感到不安,而是错误被getStudent中的捕获之一所捕获。的NodeJS /捕获的功能似乎作用

顺便提及,我想出误差是做的,而不是状态(0)的状态(200)。

我应该如何重组所以这些渔获所以它们不影响主代码?还是我完全滥用回调概念?看起来像“then/catch”是处理与mssql异步的正确方法。 http://localhost:3000/student在浏览器中:

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

我通过输入运行上面。

控制台输出:

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:修订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; 
}); 

结果:

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 

回答

1

回调的概念是好的,你还可以创建在getStudent功能自己的承诺,并将其返回,这将使你的代码更易读。问题与response.status(0).send(result); xhr调用不存在这种状态,否则会产生错误。在这里,你可以得到一些有用的状态与他们的全球可接受的使用情况http://www.restapitutorial.com/httpstatuscodes.html

+0

是的,我想我在原来的问题时说,使用(200),而不是(0)固定的一个问题。但更大的问题是异步时机。 – NealWalters

2

你似乎混合Promises和回调的方式,使一切更容易混淆,它需要我。承诺的一般模式是返回它们,然后致电then,这将给您从已解决的承诺中获得回报。请记住,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 
    }) 
}) 

这里有一个配对这个示例有助于展示承诺链接的动作,并使用简单的异步承诺模拟来返回您发送的内容。您可以取消注释throw() s到怎么看错误冒泡:

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

这是现货,另外阅读http://solutionoptimist.com/2013/12/27/javascript-promise-chains-2/可能有帮助 – phuhgh

+0

谢谢,你是对的;我正在混合来自两个不同来源的例子。所以现在,我删除了回调,代码看起来更干净。但 - 我看到“Fall through 1”和app.get/getStudent中的“.THEN”在查询完成之前正在运行,并给出错误:“TypeError:Can not read property'then'of'undefined”(因为记录集不是还没有被检索)所以我有一个异步问题的地方。我只需要让我的电话getStudent同步? – NealWalters

+0

添加了我的新代码和console.log – NealWalters