NodejS .then(promise)调用者在异步功能完成之前得到了不好的结果
这是我在这里提出的问题的重新启动:然后/捕获NodeJS函数中似乎正在捕获函数外部的代码我改变了很多次,尽管这很相似,但我认为这基本上是一个不同的问题.
This is a reboot of the question I asked here: NodeJS then/catch in a function seems to be catching code outside the function I changed so many times, I think this is basically a different question, although similar.
我的NodeJS代码:
My NodeJS code:
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:
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语句正在运行,并且可能在函数仍试图获取其数据库连接的同时获取了未定义".
So what this tells me is that the .then statement of the calling routine is running and getting the "undefined" probably while the function is still trying to get it's database connection.
如何保持异步最佳实践/模型,并在检索到数据后能够正确处理我的数据?
How do I keep the Async best practice/model, and be able to handle my data properly after it has been retrieved?
我读到这个问题:节点在异步功能完成之前退出在目标上-但这就是答案,我如何将其包装在我的SQL请求中?我要尝试一下,如果知道了,我会在这里发布答案.
I read this question: Node exits before async function completes which seems on target - but if that's the answer, how would I wrap that around my SQL request? I'm going to try it, and if I get it, I will post answer here.
修订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
此时,程序似乎已挂起.永不返回浏览器.
At this point the program seems to hang. Never goes back to browser.
getStudent
不返回任何内容(因此为 undefined
),因此它没有然后
属性.
getStudent
does not return anything (so undefined
), so it does not have the then
property.
它应该返回一个承诺,因此请在此处添加 return
:
It should return a promise, so add return
here:
return sql.connect(config).then(pool => {
...,然后将 sql.on
调用移至该返回之前.
... and move the sql.on
call before that return.
第二,取消注释此行:
// return result;
因为需要沿着承诺链传递结果.您将在 app.get
回调函数中以 recordset
的形式获取其值.
Because that result needs to be passed along the promise chain. You'll fetch its value as recordset
in the app.get
callback function.