NodejS .then(promise)调用程序在异步函数完成之前得到错误的结果

时间:2017-07-31 19:04:31

标签: node.js asynchronous promise

这是我在这里问的问题的重新启动: NodeJS then/catch in a function seems to be catching code outside the function 我改变了很多次,我认为这基本上是一个不同的问题,虽然相似。

我的NodeJS代码:

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

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

var lookupStudentId = 31; 


const sql = require('mssql');

var connPool = new sql.ConnectionPool(config);

function getStudent(studentID) 
{
    console.log("getStudent"); 

    sql.connect(config).then(pool => {
        // Query 
        return pool.request()
        .input('input_parameter', sql.Int, studentID)
        .query('select student_firstname, student_lastname from students where student_id = @input_parameter')
    }).then(function(result) {
        console.log("getStudent:then(result=>"); 
        console.dir(result);
        sql.close(); 
        //return result; 
    })
    .catch(err => {
        // ... error checks 
        console.log("DB Error1: " + err); 
    })

    sql.on('error', err => {
        // ... error handler 
        console.log("DB Error2: " + err); 
    })
}


app.get('/student', function(request, response){
    console.log('Neal Test1 - start app.get for /student lookupStudentId = ' + lookupStudentId); 
    getStudent(lookupStudentId)
        .then (function(recordset)  {  /* this is line 82 of the error */
            objType = Object.prototype.toString.call(recordset);
            console.log('Back from getStudent objType=' + objType  ); 
            console.dir('recordSet=' + recordSet); 
            response.status(200).send(recordset); 
        })
        .catch (function(err) {
            objType = Object.prototype.toString.call(recordset);
            console.log('ERR: Back from getStudent objType=' + objType  ); 
            console.log("error400=" + err); 
            console.log("empty test=" + Object.keys(err).length); 
            response.status(400).send(err);
        })
    return;
});

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

Console.Log:

Express server is listening on port 3000
Neal Test1 - start app.get for /student lookupStudentId = 31
getStudent
TypeError: Cannot read property 'then' of undefined
    at C:\Software\nodejs\wisdomcalls\indexPromises.js:82: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)
getStudent:then(result=>
{ recordsets: [ [ [Object] ] ],
  recordset:
   [ { student_firstname: 'Jonah                ',
       student_lastname: 'Hill                    ' } ],
  output: {},
  rowsAffected: [ 1 ] }

所以这告诉我的是调用例程的.then语句正在运行并且当函数仍在尝试获取它的数据库连接时可能会获得“未定义”。

如何保留Async最佳实践/模型,并能够在检索到数据后正确处理数据?

我读到了这个问题:Node exits before async function completes似乎是目标 - 但如果这就是答案,我将如何围绕我的SQL请求进行包装?我要去尝试一下,如果我得到它,我会在这里发布答案。

修订版2

function getStudent(studentID) 
{
    console.log("---------getStudent"); 

    sql.on('error', err => {
        // ... error handler 
        console.log("DB Error2: " + err); 
    })

    return sql.connect(config).then(pool => {
            // Query 
            return pool.request()
            .input('input_parameter', sql.Int, studentID)
            .query('select student_firstname, student_lastname from students where student_id = @input_parameter')
        }).then(function(result) {
            console.log("getStudent:then(result=>"); 
            console.dir(result);
            sql.close(); 
            return result; 
        })
        .catch(err => {
            // ... error checks 
            console.log("DB Error1: " + err); 
        })

}


app.get('/student', function(request, response){
    console.log('==================Neal Test1 - start app.get for /student lookupStudentId = ' + lookupStudentId+ '======================='); 

    //process.on('unhandledRejection', r => function(){});

    getStudent(lookupStudentId)
        .then (function(recordset)  {
            console.log('Back from getStudent'); 
            objType = Object.prototype.toString.call(recordset);
            console.log('objType=' + objType  ); 
            console.dir('recordSet=' + recordSet); 
            response.status(200).send(recordset); 
        })
        .catch (function(err) {
            objType = Object.prototype.toString.call(recordset);
            console.log('ERR: Back from getStudent objType=' + objType  ); 
            console.log("error400=" + err); 
            console.log("empty test=" + Object.keys(err).length); 
            response.status(400).send(err);
        })
    return;
});

CONSOLE.LOG:

    ==================Neal Test1 - start app.get for /student lookupStudentId = 31=======================
    ---------getStudent
    getStudent:then(result=>
    { recordsets: [ [ [Object] ] ],
      recordset:
       [ { student_firstname: 'Jonah                ',
           student_lastname: 'Hill                    ' } ],
      output: {},
      rowsAffected: [ 1 ] }
Back from getStudent
objType=[object Object]
(node:26212) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): ReferenceError: recordset is not defined

此时程序似乎挂了。永远不要回到浏览器。

1 个答案:

答案 0 :(得分:1)

getStudent不返回任何内容(因此undefined),因此它没有then属性。

它应该返回一个承诺,所以在这里添加return

return sql.connect(config).then(pool => {

...并在返回之前移动sql.on来电。

其次,取消注释这一行:

// return result;

因为该结果需要沿着承诺链传递。您将在recordset回调函数中将其值取为app.get