节点&connection.query内部的MySQL-connection.query-对象属性不可访问
Node & MySQL - connection.query inside connection.query - Object property not accessible
我遇到了一个非常尴尬的问题。我创建一个池,连接到数据库,创建一个连接和查询,获取结果,做一些事情,然后我必须创建另一个连接并查询,但实际上它必须是动态的,所以我在包含数据的Array teacherHours
上循环。
然后发生了更多的Code,我必须创建一个额外的循环,因为我的teacherHours
数组的某些元素必须多次尝试才能从即将到来的查询中获得正确的响应。
因此,接下来是另一个循环,它应该循环与availableHours > 0
一样长的时间。现在,这是一切向左发展的地方。
在第二个循环中发生了大量代码,我准备了第二个查询,调用connection.query(),在回调函数中准备了第三个查询(在做了一些其他事情之后),这实际上是Node把我赶出去的地方。
它给了我TypeError: Cannot read property 'tid' of undefined
。第三次查询需要访问tid
,所以我尝试像以前一样访问它,但Node不允许。
我知道查询返回有用的数据(行),所以查询但不接收数据不会成为问题。事实上,我console.log("the rowRIDS"+rowRIDS);
是第二个查询的结果,我看到它返回了2行,就在那之后,它给了我错误。
对我来说也很奇怪的是,我的两个循环中的所有console.log都被记录了下来,而我的第二个查询的console.log(包含2行)在循环结束后被记录了起来,因为查询是嵌套的,返回的2行和错误不应该出现在循环的第一次迭代中,因为代码应该在那时访问第二个询问。
顺便说一句,我试图设置一个硬编码的数字而不是tid
,只是为了让下一个属性datum
出错。我有点觉得变量teacherHours超出了范围,但它应该是一个全局变量。
为了更好地理解我所说的内容,我复制了代码并取消了所有javascript代码的注释,在这里我填充和计算内容。任何帮助都会非常好,它已经尝试了将近7个小时;没有任何运气的错误。非常感谢。
pool.getConnection(function(err, connection){
if (err) throw err;
connection.query('SELECT * FROM teachers_teaching_tbl WHERE fwdid = 1 ', function(err, rows, fields) {
if (err) {
console.error('error querying: ' + err.stack);
return;
}
rowArray=rows;
console.log(rowArray);
//
// HERE HAPPENS
// A LOOOOT OF STUFF
//
// AND teacherHours IS BEING POPULATED
//
// THEN COMES A FOR LOOP
for(var i=0; i<teacherHours.length;i++){
//
// MORE STUFF
//
//AND ANOTHER LOOP
while(availableHours>0){//do{ ORIGINALLY I TRIED WITH A DO WHILE LOOP
//
// AGAIN A BUNCH OF STUFF
//
// NOW I'M PREPARING MY NEXT QUERY
//
var myQueryGetFreeRoom=" SELECT rms.rid FROM rooms_tbl as rms WHERE NOT EXISTS ( ";
myQueryGetFreeRoom+=" SELECT NULL FROM classes_tbl as cls ";
myQueryGetFreeRoom+=" WHERE ( (cls.bis > '"+bisMinus1+"' AND cls.bis <= '"+realBis+"' ) OR ( cls.von > '"+bisMinus1+"' AND cls.von < '"+realBis+"' ) ) AND (cls.datum = '"+teacherHours[i].datum.getFullYear()+"-"+(teacherHours[i].datum.getMonth()+1)+"-"+teacherHours[i].datum.getDate()+"') AND (cls.rid=rms.rid) ) ";
//
//
connection.query(myQueryGetFreeRoom, function(err, rowRIDS, fields) {
if (err) {
console.error('error querying: ' + err.stack);
return;
}
roomIDs=rowRIDS;
console.log("the rowRIDS"+rowRIDS);
//
// MORE STUFF
// HAPPENING
//
if(roomIDs.length>0){
//
// PREPARING QUERY NO.3 - WHICH IS WHERE MY ERROR POINTS - TO THE USE OF tid PROPERTY
//
var myQueryBookClass = " INSERT INTO classes_tbl ( rid , tid , belegtAnz, datum, von , bis ) ";
myQueryBookClass+=" VALUES ( "+Math.floor(Math.random() * roomIDs.length)+", "+teacherHours[i].tid+" , 0, '"+teacherHours[i].datum.getFullYear()+"-"+(teacherHours[i].datum.getMonth()+1)+"-"+teacherHours[i].datum.getDate()+"' , '"+bisMinus1+"' , '"+realBis+"' ) ";
console.log("myQueryBookClass: "+myQueryBookClass);
availableHours = 0;
//
// HERE WAS SUPPOSED TO FOLLOW QUERY 3 - myQueryBookClass
//
// BUT SINCE I DONT EVEN GET INSIDE HERE IT IS IN COMMENTS
//
/*connection.query(myQueryBookClass, function(err, insertRows, fields){
if(err){
console.error('error querying: '+err.stack);
return;
}
console.log("Inserted Rows: "+ insertRows);
}); */
} else {
availableHours= availableHours - 1;
//
// STUFF HAPPENING
//
}
});
availableHours= availableHours - 1;
}//while(availableHours>0);
//
}
connection.release(function(err){
if (err){
console.error('error disconnecting: ' + err.stack);
return;
}
});
});
});
我认为您来自Python、Java等非异步语言。这就是为什么Node(即JavaScript)似乎会给您带来麻烦,但实际上并非如此。
代码中的问题是在同一个while
循环中同时同步执行类似query
的异步函数。您需要使用像async
这样的模块,它可以帮助异步运行和收集结果。
这是更新后的代码。
var async = require('async'),
connection;
async.waterfall([
function (cb) {
pool.getConnection(cb);
},
function (conn, cb) {
connection = conn;
connection.query('SELECT * FROM teachers_teaching_tbl WHERE fwdid = 1', cb);
},
function (rows, fields, cb) {
rowArray = rows;
console.log(rowArray);
// HERE HAPPENS
// A LOOOOT OF STUFF
//
// AND teacherHours IS BEING POPULATED
//
// THEN COMES A FOR LOOP
async.eachSeries(teacherHours, function (teacherHour, done) {
// MORE STUFF
//
//AND ANOTHER LOOP
async.whilst(function () {
return availableHours > 0;
}, function (cb) {
// AGAIN A BUNCH OF STUFF
//
// NOW I'M PREPARING MY NEXT QUERY
//
var myQueryGetFreeRoom =
"SELECT rms.rid FROM rooms_tbl AS rms WHERE NOT EXISTS ("
+ "SELECT NULL FROM classes_tbl AS cls"
+ " WHERE ("
+ "(cls.bis > '" + bisMinus1 + "' AND cls.bis <= '" + realBis + "')"
+ " OR (cls.von > '" + bisMinus1 + "' AND cls.von < '" + realBis + "')"
+ ") AND ("
+ "cls.datum = '" + teacherHour.datum.getFullYear() + "-" + (teacherHour.datum.getMonth() + 1) + "-" + teacherHour.datum.getDate() + "'"
+ ") AND cls.rid = rms.rid";
async.waterfall([
function (cb) {
connection.query(myQueryGetFreeRoom, cb);
},
function(rowRIDS, fields, cb) {
roomIDs = rowRIDS;
console.log("the rowRIDS" + rowRIDS);
//
// MORE STUFF
// HAPPENING
//
if (roomIDs.length > 0) {
//
// PREPARING QUERY NO.3 - WHICH IS WHERE MY ERROR POINTS - TO THE USE OF tid PROPERTY
//
var myQueryBookClass = "INSERT INTO classes_tbl (rid, tid, belegtAnz, datum, von, bis) VALUES ("
+ Math.floor(Math.random() * roomIDs.length)
+ ", " + teacherHour.tid
+ ", 0, '" + teacherHour.datum.getFullYear() + "-" + (teacherHour.datum.getMonth() + 1) + "-" + teacherHour.datum.getDate() + "', '" + bisMinus1 + "', '" + realBis + "')";
console.log("myQueryBookClass: " + myQueryBookClass);
availableHours = 0;
//
// HERE WAS SUPPOSED TO FOLLOW QUERY 3 - myQueryBookClass
//
// BUT SINCE I DONT EVEN GET INSIDE HERE IT IS IN COMMENTS
//
connection.query(myQueryBookClass, function (err, insertRows, fields) {
if (err) {
console.error('error querying: '+err.stack);
return;
}
console.log("Inserted Rows: "+ insertRows);
// Here do whatever you need to do, then call the callback;
cb();
});
} else {
--availableHours;
//
// STUFF HAPPENING
//
cb();
}
}
], function (err) {
if (!err) {
// Notice that you are decrementing the `availableHours` twice here and above.
// Make sure this is what you want.
--availableHours;
}
cb(err);
});
}, done);
}, function (err) {
connection.release(function (err) {
if (err) {
console.error('error disconnecting: ' + err.stack);
return;
}
});
});
}
], function (err) {
conn && pool.release(conn);
err && throw err;
});
下次请正确格式化代码以获得更好的可读性,这将有助于您更快地获得答案,并出于同样的目的将问题文本拆分为段落。
解释
有四个嵌套的async
流:
async.waterfall
-> async.eachSeries
-> async.whilst
-> async.waterfall
基本上,
async.waterfall
库允许您执行一系列函数。- 每个下一个函数将仅在前一个函数返回响应后执行
- 为了指示一个函数已经完成并且结果可用,它必须调用回调,在我们的例子中它是
cb
(你可以随意调用它,例如callback
)。规则是调用它,否则,下一个函数将永远不会执行,因为上一个函数似乎还没有完成它的工作 一旦上一个函数完成,它就会调用具有以下签名的
cb
:cb(err, connection);
如果在请求连接时出现错误,则整个
async.waterfall
将中断,并执行最终的回调函数。- 如果没有错误,连接将作为第二个参数提供。
async
模块将上一个函数的所有自变量作为第一、第二等自变量传递给下一个函数,这就是为什么第二个函数接收conn
作为第一自变量的原因 每个下一个函数都将接收回调
cb
作为最后一个参数,您最终必须在作业完成时调用它。因此,在第一个
async.waterfall
流中:- 它请求一个新的数据库连接
- 一旦连接可用,将执行下一个函数,该函数将向数据库发送查询
- 等待查询结果,然后一旦结果可用,就可以运行下一个函数,该函数对每一行进行迭代
async.eachSeries
允许按顺序迭代给定的值数组。在第二个
async.eachSeries
流中:- 它按顺序迭代
teacherHours
数组中的每个元素 - 一旦处理了每个元素(无论您想要什么),就必须调用
done
回调。同样,您可以像前面的async.waterfall
或callback
一样将其称为cb
。done
只是为了清楚起见,该过程已完成
- 它按顺序迭代
然后我们有了
async.whilst
,它提供了与普通while () {}
语句相同的逻辑,但异步处理循环。在第三个
async.whilst
流中:- 调用第一个函数。它的返回值指示它是否必须继续循环,即调用第二个异步函数
- 如果返回值是trust(
availableHours > 0
),则调用第二个函数 - 当异步函数完成时,它必须调用所提供的回调
cb
来指示它已经结束。然后async
模块将调用第一个函数来检查是否必须继续循环
在
async.whilst
中的这个异步函数中,我们有另一个async.waterfall
,因为您需要为每个teacherHour
向数据库发送查询。在最后的第四个
async.watercall
流中:- 它向数据库发送
SELECT
查询 - 正在等待响应。一旦
rowRIDS
可用,它就调用waterfall
中的第二个函数 - 如果存在
rowRIDS
(roomIDs.length > 0
),则向数据库发送INSERT
查询 - 一旦完成,它调用回调
cb
- 如果没有
rowRIDs
,它也会调用回调cb
,以指示作业已完成
- 它向数据库发送
JavaScript是异步的,这是一件很棒的事情。当你从其他同步语言转换时,一开始可能会很困难,但一旦你有了这个想法,就很难同步处理。它变得如此直观,以至于你会开始思考为什么其他语言不能异步工作。
我希望我能彻底解释上面的代码。享受JavaScript!太棒了!
- 引用对象中的通用值
- jQuery匹配JSON对象的部分文本
- 节点导出返回一个空对象
- 如何在Javascript中将JSon对象转换为数组
- 我可以在json对象中添加一个函数吗
- 使用JS将数组转换为json对象
- 全局变量和全局对象的属性之间有什么区别吗
- 比较从函数和生成的日期对象
- Javascript,访问一个主要对象模块模式中的每个对象
- 如果使用 lodash 将属性存在于另一个对象中,则向对象添加属性
- 调整窗口大小时,可拖动的对象会出现在容器外部
- 如何使用javascript从主svg对象动态创建svg视图框
- 如何使用json将对象列表从java转换为javascript
- 序列化数据属性中对象的最可靠方法
- 如何使用Parse.Query检索特定对象
- Parse.Query 返回的对象数少于限制
- 节点&connection.query内部的MySQL-connection.query-对象属性不可访问
- 将对象传递给Query插件,其中包含应用于的元素的数据
- AngularJS, $resource,从.query()中获取对象
- 我能在对象属性上执行query-tmpl吗?