2017-07-28 25 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