【问题标题】:NodejS .then (promise) Caller gets bad results before async function finishesNodejS .then(promise)调用者在异步函数完成之前得到不好的结果
【发布时间】:2018-01-07 11:22:26
【问题描述】:

这是我在这里提出的问题的重新启动: 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');
});

控制台日志:

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 语句正在运行并且可能在函数仍在尝试获取它的数据库连接时获得“未定义”。

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

我读到了这个问题: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;
});

控制台日志:

    ==================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

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

【问题讨论】:

    标签: node.js asynchronous promise


    【解决方案1】:

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

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

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

    ...并在返回之前移动 sql.on 调用。

    其次,取消注释这一行:

    // return result;
    

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

    【讨论】:

    • 好的,这很有帮助;即新错误现在出现在 SQL 发生之后。现在我在 console.log 中看到了这个:从 getStudent objType=[object Undefined] (node:16736) UnhandledPromiseRejectionWarning: Unhandled Promise RejectionWarning: Unhandled promise reject (rejection id: 1): ReferenceError: recordset is not defined
    • 取消注释您拥有的// return result,以便您实际上通过承诺链传递结果。
    • 仍然:UnhandledPromiseRejectionWarning(并且浏览器没有返回任何内容)。将我当前的代码作为 Revision2 添加到原始问题中。
    • 当你有一个 unhandledPromiseRejected 时,它后面的错误描述是最重要的。还是recordset is not defined吗?
    • 它在版本 2 的 console.log 中。而不是“TypeError:无法读取未定义的属性'then'”,它现在说:“未处理的承诺拒绝(拒绝 id:1):ReferenceError:未定义记录集”然后挂起。它之前没有挂起。
    猜你喜欢
    • 1970-01-01
    • 2016-05-13
    • 2019-02-22
    • 2019-03-07
    • 1970-01-01
    • 1970-01-01
    • 2016-07-16
    • 2018-04-05
    • 1970-01-01
    相关资源
    最近更新 更多