NodeJS SQL Server tedious TypeError: columns.forEach is not a function
NodeJS SQL Server tedious TypeError: columns.forEach is not a function
我正在尝试使用基于一些示例的乏味驱动程序来处理来自 SQL 服务器的结果集,但总是得到 "TypeError: columns.forEach is not a function" 错误,我无法弄清楚为什么不是为我工作。
所有模块都是最近从 npm (2018.09.21) 安装的。繁琐版本:tedious@2.6.4
https://sqlchoice.azurewebsites.net/en-us/sql-server/developer-get-started/node/sles/step/2.html
我的代码:
var express = require('express');
var router = express.Router();
var auth = require(__dirname +'/../lib/' + 'authorization');
const config = {
server : 'servername',
domain : 'MYDOMAIN',
userName : 'MYUSER',
password : 'MYPASSWORD',
options : {
rowCollectionOnRequestCompletion : true,
database : 'MYDB',
encrypt : true,
connectionTimeout : 1000,
requestTimeout : 0,
useColumnNames : true,
isolationLevel : 'READ_UNCOMITTED',
appName : 'My nodejs app',
connectionRetryInterval : 5000
},
};
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES;
require('tedious').ISOLATION_LEVEL;
var connection;
router.post('/', auth.auth, async(req, res, next) => {
try {
connection = new Connection(config);
connection.on('connect', function(err) {
if (err)
{
console.log(new Date().toUTCString() + ' : Database connection failed to database : ' + config.options.database);
}
else
{
console.log(new Date().toUTCString() + ' : Database connected : ' + this.config.server + '.' + this.config.options.database + ' Status : ' + this.state.name);
getList(res);
}
})
.on('infoMessage', infoError)
.on('errorMessage', infoError)
.on('end', end)
.on('debug', debug)
.on('error', error)
.on('databaseChange', databaseChange)
}
catch (ex)
{
console.log(new Date().toUTCString() + ' : ' + 'Error: ' + ex.message);
res.status(500);
res.send(ex.message);
}
});
function getList(res){
var query = "SELECT * FROM sysfiles;";
var request = new Request(query, function (err, rowCount, rows)
{
if (err)
{
console.log(new Date().toUTCString() + ' : ' + 'Error: ' + err);
res.write('{ "error" : "' + err + '" }');
res.end();
}
else
{
// console.log(rowCount + ' rows');
var rowarray = [];
rows.forEach(function(columns)
{
var rowdata = new Object();
columns.forEach(function(column)
{
rowdata[column.metadata.colName] = column.value;
});
rowarray.push(rowdata);
})
res.contentType('application/json');
retval = JSON.stringify(rowarray);
//if (cb)
//{
// retval = cb + '(' + retval + ');'
//}
res.write(retval);
res.end();
}
// request.on('columnMetadata', columnMetadata);
});
request.on('done', requestDone);
// request.addParameter('Pattern', TYPES.VarChar, '%' + pattern +'%');
// request.addParameter('TOP', TYPES.Null, null);
connection.execSql(request);
// connection.callProcedure(request);
}
module.exports = router;
我得到的错误信息:
C:\mypath\myapp\routes\route1.js:60
columns.forEach(function(column)
^
TypeError: columns.forEach is not a function
at C:\mypath\myapp\routes\route1.js:60:17
at Array.forEach (<anonymous>)
at Request.userCallback (C:\mypath\myapp\routes\route1.js:57:12)
at Request._this.callback (C:\mypath\myapp\node_modules\tedious\lib\request.js:60:27)
at Connection.endOfMessageMarkerReceived (C:\mypath\myapp\node_modules\tedious\lib\connection.js:1922:20)
at Connection.dispatchEvent (C:\mypath\myapp\node_modules\tedious\lib\connection.js:1004:38)
at Parser.<anonymous> (C:\mypath\myapp\node_modules\tedious\lib\connection.js:805:18)
at Parser.emit (events.js:182:13)
at Parser.<anonymous> (C:\mypath\myapp\node_modules\tedious\lib\token\token-stream-parser.js:54:15)
at Parser.emit (events.js:182:13)
Waiting for the debugger to disconnect
更新
正如 "Matt Kuhn" 和 "Think - Twice" 所指出的,问题出在列的类型上。感谢他们!
问题是 config.options 部分中的 "useColumnNames : true"。删除它解决了这个问题。我们可以使用 then "useColumnNames : true" 但我们需要按名称引用列而不是遍历数组。
您的代码不会调用 tedious 公开的 request.on 事件。您还可以通过调用 typeof 来测试以确保列是一个数组。您的错误意味着列不是数组,实际上可能未定义。
这是他们网站上最小示例的代码:
function executeStatement() {
request = new Request("SELECT * FROM sysfiles", function(err, rowCount) {
if (err) {
console.log(err);
} else {
console.log(rowCount + ' rows');
}
connection.close();
});
request.on('row', function(columns) {
console.log("columns", columns); //should show your array
console.log("typeof columns", typeof columns); //should by array
columns.forEach(function(column) {
if (column.value === null) {
console.log('NULL');
} else {
console.log(column.value);
}
});
});
request.on('done', function(rowCount, more) {
console.log(rowCount + ' rows returned');
});
// In SQL Server 2000 you may need: connection.execSqlBatch(request);
connection.execSql(request);
}
在执行 forEach
之前,您需要检查列是数组还是未定义
rows.forEach(function(columns)
{
var rowdata = new Object();
if(columns){
columns.forEach(function(column)
{
rowdata[column.metadata.colName] = column.value;
});
}
rowarray.push(rowdata);
});
我正在尝试使用基于一些示例的乏味驱动程序来处理来自 SQL 服务器的结果集,但总是得到 "TypeError: columns.forEach is not a function" 错误,我无法弄清楚为什么不是为我工作。
所有模块都是最近从 npm (2018.09.21) 安装的。繁琐版本:tedious@2.6.4
https://sqlchoice.azurewebsites.net/en-us/sql-server/developer-get-started/node/sles/step/2.html
我的代码:
var express = require('express');
var router = express.Router();
var auth = require(__dirname +'/../lib/' + 'authorization');
const config = {
server : 'servername',
domain : 'MYDOMAIN',
userName : 'MYUSER',
password : 'MYPASSWORD',
options : {
rowCollectionOnRequestCompletion : true,
database : 'MYDB',
encrypt : true,
connectionTimeout : 1000,
requestTimeout : 0,
useColumnNames : true,
isolationLevel : 'READ_UNCOMITTED',
appName : 'My nodejs app',
connectionRetryInterval : 5000
},
};
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES;
require('tedious').ISOLATION_LEVEL;
var connection;
router.post('/', auth.auth, async(req, res, next) => {
try {
connection = new Connection(config);
connection.on('connect', function(err) {
if (err)
{
console.log(new Date().toUTCString() + ' : Database connection failed to database : ' + config.options.database);
}
else
{
console.log(new Date().toUTCString() + ' : Database connected : ' + this.config.server + '.' + this.config.options.database + ' Status : ' + this.state.name);
getList(res);
}
})
.on('infoMessage', infoError)
.on('errorMessage', infoError)
.on('end', end)
.on('debug', debug)
.on('error', error)
.on('databaseChange', databaseChange)
}
catch (ex)
{
console.log(new Date().toUTCString() + ' : ' + 'Error: ' + ex.message);
res.status(500);
res.send(ex.message);
}
});
function getList(res){
var query = "SELECT * FROM sysfiles;";
var request = new Request(query, function (err, rowCount, rows)
{
if (err)
{
console.log(new Date().toUTCString() + ' : ' + 'Error: ' + err);
res.write('{ "error" : "' + err + '" }');
res.end();
}
else
{
// console.log(rowCount + ' rows');
var rowarray = [];
rows.forEach(function(columns)
{
var rowdata = new Object();
columns.forEach(function(column)
{
rowdata[column.metadata.colName] = column.value;
});
rowarray.push(rowdata);
})
res.contentType('application/json');
retval = JSON.stringify(rowarray);
//if (cb)
//{
// retval = cb + '(' + retval + ');'
//}
res.write(retval);
res.end();
}
// request.on('columnMetadata', columnMetadata);
});
request.on('done', requestDone);
// request.addParameter('Pattern', TYPES.VarChar, '%' + pattern +'%');
// request.addParameter('TOP', TYPES.Null, null);
connection.execSql(request);
// connection.callProcedure(request);
}
module.exports = router;
我得到的错误信息:
C:\mypath\myapp\routes\route1.js:60
columns.forEach(function(column)
^
TypeError: columns.forEach is not a function
at C:\mypath\myapp\routes\route1.js:60:17
at Array.forEach (<anonymous>)
at Request.userCallback (C:\mypath\myapp\routes\route1.js:57:12)
at Request._this.callback (C:\mypath\myapp\node_modules\tedious\lib\request.js:60:27)
at Connection.endOfMessageMarkerReceived (C:\mypath\myapp\node_modules\tedious\lib\connection.js:1922:20)
at Connection.dispatchEvent (C:\mypath\myapp\node_modules\tedious\lib\connection.js:1004:38)
at Parser.<anonymous> (C:\mypath\myapp\node_modules\tedious\lib\connection.js:805:18)
at Parser.emit (events.js:182:13)
at Parser.<anonymous> (C:\mypath\myapp\node_modules\tedious\lib\token\token-stream-parser.js:54:15)
at Parser.emit (events.js:182:13)
Waiting for the debugger to disconnect
更新
正如 "Matt Kuhn" 和 "Think - Twice" 所指出的,问题出在列的类型上。感谢他们!
问题是 config.options 部分中的 "useColumnNames : true"。删除它解决了这个问题。我们可以使用 then "useColumnNames : true" 但我们需要按名称引用列而不是遍历数组。
您的代码不会调用 tedious 公开的 request.on 事件。您还可以通过调用 typeof 来测试以确保列是一个数组。您的错误意味着列不是数组,实际上可能未定义。
这是他们网站上最小示例的代码:
function executeStatement() {
request = new Request("SELECT * FROM sysfiles", function(err, rowCount) {
if (err) {
console.log(err);
} else {
console.log(rowCount + ' rows');
}
connection.close();
});
request.on('row', function(columns) {
console.log("columns", columns); //should show your array
console.log("typeof columns", typeof columns); //should by array
columns.forEach(function(column) {
if (column.value === null) {
console.log('NULL');
} else {
console.log(column.value);
}
});
});
request.on('done', function(rowCount, more) {
console.log(rowCount + ' rows returned');
});
// In SQL Server 2000 you may need: connection.execSqlBatch(request);
connection.execSql(request);
}
在执行 forEach
之前,您需要检查列是数组还是未定义 rows.forEach(function(columns)
{
var rowdata = new Object();
if(columns){
columns.forEach(function(column)
{
rowdata[column.metadata.colName] = column.value;
});
}
rowarray.push(rowdata);
});