数组长度报告不一致
Array length inconsistently reported
我十年前开发了一个 MS Access 桌面数据库应用程序,我试图使用节点、电子和 mysql 重建,现在我是一个正在恢复的 windows 用户。
我首先在导入数据库的必要部分后在应用程序中重新创建最简单的表单:https://imgur.com/a/oRfcsXw。
问题出在数据控件的操作(左下角),特别是在使用新记录按钮(“>+”)时。虽然它有时会正确地增加记录号(屏幕截图中的“336”),但有时不会。当它粘住时,继续添加记录最终会使它在最终再次粘住之前突然赶上来。调试表明原因是 newRecord()
中的 rows.length
没有被正确报告。
可以肯定地说这与我无法完全理解异步执行、回调、promises 和 async/await 令人沮丧的莫名其妙有关,尽管我的智力还算中等,并且在过去四天。我想在我能够更好地理解这个概念之前,我只需要看一个适用于我的情况的例子来说明如何做。所以请随意忽略下面这个菜鸟代码中的许多缺陷,其中一些他知道,而且我敢肯定有很多他不知道,只关注我如何获得准确的 rows.length
。
<script>
var new_record = false;
var position = 0;
var last_record = 0;
var sql_columns = [];
var sql_values = [];
var mysql = require('mysql2/promise');
var bluebird = require('bluebird');
var pool = mysql.createPool({
host : 'localhost',
user : 'user',
password : 'password',
database : 'db',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0,
Promise: bluebird
});
async function getData() {
new_record = false;
const [rows, fields] = await pool.query('SELECT * FROM qryStudents');
last_record = rows.length - 1;
if (position > last_record) { position = last_record; }
refreshDataControl();
document.getElementById("student-id").value = rows[position].idsStudentID;
document.getElementById("first-name").value = rows[position].chrFName;
document.getElementById("last-name").value = rows[position].chrLName;
document.getElementById("ssn").value = rows[position].chrSSN;
if (rows[position].ysnActive == 1 || rows[position].ysnActive == true) {
document.getElementById("active").checked = true;
} else if (rows[position].ysnActive == 0 || rows[position].ysnActive == false) {
document.getElementById("active").checked = false;
}
document.getElementById("enrollment-address1").value = rows[position].chrAddress1;
document.getElementById("enrollment-address2").value = rows[position].chrAddress2;
document.getElementById("enrollment-city").value = rows[position].chrCity;
document.getElementById("enrollment-state").value = rows[position].chrState;
document.getElementById("enrollment-zip").value = rows[position].chrZIP;
document.getElementById("enrollment-phone").value = rows[position].chrPhone;
document.getElementById("lda-address1").value = rows[position].chrLDAAddress1;
document.getElementById("lda-address2").value = rows[position].chrLDAAddress2;
document.getElementById("lda-city").value = rows[position].chrLDACity;
document.getElementById("lda-state").value = rows[position].chrLDAState;
document.getElementById("lda-zip").value = rows[position].chrLDAZIP;
document.getElementById("lda-phone").value = rows[position].chrLDAPhone;
}
async function saveRecord() {
var sql;
var i;
if (sql_columns.length == 0) { return; }
if (new_record == true) {
sql = "INSERT INTO tblStudents SET ";
if (sql_columns.indexOf("ysnActive") == -1) {
sql_columns.push("ysnActive");
sql_values.push(document.getElementById("active").checked);
}
} else { sql = "UPDATE tblStudents SET "; }
for (i = 0; i < sql_columns.length; i++) {
if (i > 0) { sql = sql + ", "; }
sql = sql + sql_columns[i] + " = ?";
}
if (new_record == false) { sql = sql + " WHERE idsStudentID = ?;"; } else { sql = sql + ";"; }
await pool.query(sql, sql_values);
sql_columns = [];
sql_values = [];
}
function buildSQL(type, name, id) {
var index = sql_columns.indexOf(name);
if (index == -1) { sql_columns.push(name); }
if (type == "text") {
if (index == -1) { sql_values.push(document.getElementById(id).value); } else { sql_values[index] = document.getElementById(id).value; }
} else if (type == "checkbox") {
if (index == -1) { sql_values.push(document.getElementById(id).checked); } else { sql_values[index] = document.getElementById(id).checked; }
}
if (new_record == false) { sql_values.push(document.getElementById("student-id").value); }
}
async function deleteRecord() {
const { dialog } = require('electron').remote;
const options = {
type: 'question',
buttons: ['Yes', 'No'],
defaultId: 1,
title: 'Question',
message: 'Do you want to do this?',
}
var choice = dialog.showMessageBoxSync(null, options);
if (choice == 0) {
var sql = "DELETE FROM tblStudents WHERE idsStudentID = " + document.getElementById("student-id").value;
await pool.query(sql);
getData();
}
}
function firstRecord() {
saveRecord();
position = 0;
getData();
}
function previousRecord() {
saveRecord();
position--;
getData();
}
function nextRecord() {
saveRecord();
position++;
getData();
}
function lastRecord() {
saveRecord();
position = last_record;
getData();
}
async function newRecord() {
saveRecord();
const [rows, fields] = await pool.query('SELECT * FROM qryStudents');
new_record = true;
last_record = rows.length - 1;
position = last_record + 1;
console.log("NR: rows.length = " + rows.length + ", position = " + position + ", last_record = " + last_record);
refreshDataControl();
}
function refreshDataControl() {
console.log("RDC: last_record = " + last_record + ", position + 1 = " + (position + 1));
console.log("------------------------------------------------");
document.getElementById("record-number").value = position + 1;
if (position == 0) {
document.getElementById("first-record").disabled = true;
document.getElementById("previous-record").disabled = true;
document.getElementById("next-record").disabled = false;
document.getElementById("last-record").disabled = false;
} else if (position >= last_record) {
document.getElementById("first-record").disabled = false;
document.getElementById("previous-record").disabled = false;
document.getElementById("next-record").disabled = true;
document.getElementById("last-record").disabled = true;
} else {
document.getElementById("first-record").disabled = false;
document.getElementById("previous-record").disabled = false;
document.getElementById("next-record").disabled = false;
document.getElementById("last-record").disabled = false;
}
}
window.resizeTo(550, 700);
window.onload = getData();
</script>
调试输出显示前两个 newRecord()
运行 正常运行,随后五个实例 rows.length
被错误报告,然后赶上最后的 运行。
[4151:0215/134309.258750:INFO:CONSOLE(300)] "RDC: last_record = 331, position + 1 = 333", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134309.258909:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)
[4151:0215/134315.820950:INFO:CONSOLE(294)] "NR: rows.length = 333, position = 333, last_record = 332", source: file:///home/antioch/enrollmentdb/students-enrollments.html (294)
[4151:0215/134315.821515:INFO:CONSOLE(300)] "RDC: last_record = 332, position + 1 = 334", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134315.822020:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)
[4151:0215/134321.729763:INFO:CONSOLE(294)] "NR: rows.length = 333, position = 333, last_record = 332", source: file:///home/antioch/enrollmentdb/students-enrollments.html (294)
[4151:0215/134321.729865:INFO:CONSOLE(300)] "RDC: last_record = 332, position + 1 = 334", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134321.729974:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)
[4151:0215/134333.178796:INFO:CONSOLE(294)] "NR: rows.length = 334, position = 334, last_record = 333", source: file:///home/antioch/enrollmentdb/students-enrollments.html (294)
[4151:0215/134333.178873:INFO:CONSOLE(300)] "RDC: last_record = 333, position + 1 = 335", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134333.178944:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)
[4151:0215/134339.487472:INFO:CONSOLE(294)] "NR: rows.length = 335, position = 335, last_record = 334", source: file:///home/antioch/enrollmentdb/students-enrollments.html (294)
[4151:0215/134339.488114:INFO:CONSOLE(300)] "RDC: last_record = 334, position + 1 = 336", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134339.488276:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)
[4151:0215/134344.938782:INFO:CONSOLE(294)] "NR: rows.length = 336, position = 336, last_record = 335", source: file:///home/antioch/enrollmentdb/students-enrollments.html (294)
[4151:0215/134344.939238:INFO:CONSOLE(300)] "RDC: last_record = 335, position + 1 = 337", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134344.939395:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)
[4151:0215/134350.297774:INFO:CONSOLE(294)] "NR: rows.length = 337, position = 337, last_record = 336", source: file:///home/antioch/enrollmentdb/students-enrollments.html (294)
[4151:0215/134350.297856:INFO:CONSOLE(300)] "RDC: last_record = 336, position + 1 = 338", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134350.297931:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)
[4151:0215/134355.734959:INFO:CONSOLE(294)] "NR: rows.length = 339, position = 339, last_record = 338", source: file:///home/antioch/enrollmentdb/students-enrollments.html (294)
[4151:0215/134355.735069:INFO:CONSOLE(300)] "RDC: last_record = 338, position + 1 = 340", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134355.735468:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)```
答案似乎很简单,只需在 newRecord()
中将 await
添加到 saveRecord()
。
新的和改进的 newRecord()
:
async function newRecord() {
await saveRecord();
const [rows, fields] = await pool.query('SELECT * FROM qryStudents');
new_record = true;
last_record = rows.length - 1;
position = last_record + 1;
refreshDataControl();
}
我十年前开发了一个 MS Access 桌面数据库应用程序,我试图使用节点、电子和 mysql 重建,现在我是一个正在恢复的 windows 用户。
我首先在导入数据库的必要部分后在应用程序中重新创建最简单的表单:https://imgur.com/a/oRfcsXw。
问题出在数据控件的操作(左下角),特别是在使用新记录按钮(“>+”)时。虽然它有时会正确地增加记录号(屏幕截图中的“336”),但有时不会。当它粘住时,继续添加记录最终会使它在最终再次粘住之前突然赶上来。调试表明原因是 newRecord()
中的 rows.length
没有被正确报告。
可以肯定地说这与我无法完全理解异步执行、回调、promises 和 async/await 令人沮丧的莫名其妙有关,尽管我的智力还算中等,并且在过去四天。我想在我能够更好地理解这个概念之前,我只需要看一个适用于我的情况的例子来说明如何做。所以请随意忽略下面这个菜鸟代码中的许多缺陷,其中一些他知道,而且我敢肯定有很多他不知道,只关注我如何获得准确的 rows.length
。
<script>
var new_record = false;
var position = 0;
var last_record = 0;
var sql_columns = [];
var sql_values = [];
var mysql = require('mysql2/promise');
var bluebird = require('bluebird');
var pool = mysql.createPool({
host : 'localhost',
user : 'user',
password : 'password',
database : 'db',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0,
Promise: bluebird
});
async function getData() {
new_record = false;
const [rows, fields] = await pool.query('SELECT * FROM qryStudents');
last_record = rows.length - 1;
if (position > last_record) { position = last_record; }
refreshDataControl();
document.getElementById("student-id").value = rows[position].idsStudentID;
document.getElementById("first-name").value = rows[position].chrFName;
document.getElementById("last-name").value = rows[position].chrLName;
document.getElementById("ssn").value = rows[position].chrSSN;
if (rows[position].ysnActive == 1 || rows[position].ysnActive == true) {
document.getElementById("active").checked = true;
} else if (rows[position].ysnActive == 0 || rows[position].ysnActive == false) {
document.getElementById("active").checked = false;
}
document.getElementById("enrollment-address1").value = rows[position].chrAddress1;
document.getElementById("enrollment-address2").value = rows[position].chrAddress2;
document.getElementById("enrollment-city").value = rows[position].chrCity;
document.getElementById("enrollment-state").value = rows[position].chrState;
document.getElementById("enrollment-zip").value = rows[position].chrZIP;
document.getElementById("enrollment-phone").value = rows[position].chrPhone;
document.getElementById("lda-address1").value = rows[position].chrLDAAddress1;
document.getElementById("lda-address2").value = rows[position].chrLDAAddress2;
document.getElementById("lda-city").value = rows[position].chrLDACity;
document.getElementById("lda-state").value = rows[position].chrLDAState;
document.getElementById("lda-zip").value = rows[position].chrLDAZIP;
document.getElementById("lda-phone").value = rows[position].chrLDAPhone;
}
async function saveRecord() {
var sql;
var i;
if (sql_columns.length == 0) { return; }
if (new_record == true) {
sql = "INSERT INTO tblStudents SET ";
if (sql_columns.indexOf("ysnActive") == -1) {
sql_columns.push("ysnActive");
sql_values.push(document.getElementById("active").checked);
}
} else { sql = "UPDATE tblStudents SET "; }
for (i = 0; i < sql_columns.length; i++) {
if (i > 0) { sql = sql + ", "; }
sql = sql + sql_columns[i] + " = ?";
}
if (new_record == false) { sql = sql + " WHERE idsStudentID = ?;"; } else { sql = sql + ";"; }
await pool.query(sql, sql_values);
sql_columns = [];
sql_values = [];
}
function buildSQL(type, name, id) {
var index = sql_columns.indexOf(name);
if (index == -1) { sql_columns.push(name); }
if (type == "text") {
if (index == -1) { sql_values.push(document.getElementById(id).value); } else { sql_values[index] = document.getElementById(id).value; }
} else if (type == "checkbox") {
if (index == -1) { sql_values.push(document.getElementById(id).checked); } else { sql_values[index] = document.getElementById(id).checked; }
}
if (new_record == false) { sql_values.push(document.getElementById("student-id").value); }
}
async function deleteRecord() {
const { dialog } = require('electron').remote;
const options = {
type: 'question',
buttons: ['Yes', 'No'],
defaultId: 1,
title: 'Question',
message: 'Do you want to do this?',
}
var choice = dialog.showMessageBoxSync(null, options);
if (choice == 0) {
var sql = "DELETE FROM tblStudents WHERE idsStudentID = " + document.getElementById("student-id").value;
await pool.query(sql);
getData();
}
}
function firstRecord() {
saveRecord();
position = 0;
getData();
}
function previousRecord() {
saveRecord();
position--;
getData();
}
function nextRecord() {
saveRecord();
position++;
getData();
}
function lastRecord() {
saveRecord();
position = last_record;
getData();
}
async function newRecord() {
saveRecord();
const [rows, fields] = await pool.query('SELECT * FROM qryStudents');
new_record = true;
last_record = rows.length - 1;
position = last_record + 1;
console.log("NR: rows.length = " + rows.length + ", position = " + position + ", last_record = " + last_record);
refreshDataControl();
}
function refreshDataControl() {
console.log("RDC: last_record = " + last_record + ", position + 1 = " + (position + 1));
console.log("------------------------------------------------");
document.getElementById("record-number").value = position + 1;
if (position == 0) {
document.getElementById("first-record").disabled = true;
document.getElementById("previous-record").disabled = true;
document.getElementById("next-record").disabled = false;
document.getElementById("last-record").disabled = false;
} else if (position >= last_record) {
document.getElementById("first-record").disabled = false;
document.getElementById("previous-record").disabled = false;
document.getElementById("next-record").disabled = true;
document.getElementById("last-record").disabled = true;
} else {
document.getElementById("first-record").disabled = false;
document.getElementById("previous-record").disabled = false;
document.getElementById("next-record").disabled = false;
document.getElementById("last-record").disabled = false;
}
}
window.resizeTo(550, 700);
window.onload = getData();
</script>
调试输出显示前两个 newRecord()
运行 正常运行,随后五个实例 rows.length
被错误报告,然后赶上最后的 运行。
[4151:0215/134309.258750:INFO:CONSOLE(300)] "RDC: last_record = 331, position + 1 = 333", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134309.258909:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)
[4151:0215/134315.820950:INFO:CONSOLE(294)] "NR: rows.length = 333, position = 333, last_record = 332", source: file:///home/antioch/enrollmentdb/students-enrollments.html (294)
[4151:0215/134315.821515:INFO:CONSOLE(300)] "RDC: last_record = 332, position + 1 = 334", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134315.822020:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)
[4151:0215/134321.729763:INFO:CONSOLE(294)] "NR: rows.length = 333, position = 333, last_record = 332", source: file:///home/antioch/enrollmentdb/students-enrollments.html (294)
[4151:0215/134321.729865:INFO:CONSOLE(300)] "RDC: last_record = 332, position + 1 = 334", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134321.729974:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)
[4151:0215/134333.178796:INFO:CONSOLE(294)] "NR: rows.length = 334, position = 334, last_record = 333", source: file:///home/antioch/enrollmentdb/students-enrollments.html (294)
[4151:0215/134333.178873:INFO:CONSOLE(300)] "RDC: last_record = 333, position + 1 = 335", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134333.178944:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)
[4151:0215/134339.487472:INFO:CONSOLE(294)] "NR: rows.length = 335, position = 335, last_record = 334", source: file:///home/antioch/enrollmentdb/students-enrollments.html (294)
[4151:0215/134339.488114:INFO:CONSOLE(300)] "RDC: last_record = 334, position + 1 = 336", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134339.488276:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)
[4151:0215/134344.938782:INFO:CONSOLE(294)] "NR: rows.length = 336, position = 336, last_record = 335", source: file:///home/antioch/enrollmentdb/students-enrollments.html (294)
[4151:0215/134344.939238:INFO:CONSOLE(300)] "RDC: last_record = 335, position + 1 = 337", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134344.939395:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)
[4151:0215/134350.297774:INFO:CONSOLE(294)] "NR: rows.length = 337, position = 337, last_record = 336", source: file:///home/antioch/enrollmentdb/students-enrollments.html (294)
[4151:0215/134350.297856:INFO:CONSOLE(300)] "RDC: last_record = 336, position + 1 = 338", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134350.297931:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)
[4151:0215/134355.734959:INFO:CONSOLE(294)] "NR: rows.length = 339, position = 339, last_record = 338", source: file:///home/antioch/enrollmentdb/students-enrollments.html (294)
[4151:0215/134355.735069:INFO:CONSOLE(300)] "RDC: last_record = 338, position + 1 = 340", source: file:///home/antioch/enrollmentdb/students-enrollments.html (300)
[4151:0215/134355.735468:INFO:CONSOLE(301)] "------------------------------------------------", source: file:///home/antioch/enrollmentdb/students-enrollments.html (301)```
答案似乎很简单,只需在 newRecord()
中将 await
添加到 saveRecord()
。
新的和改进的 newRecord()
:
async function newRecord() {
await saveRecord();
const [rows, fields] = await pool.query('SELECT * FROM qryStudents');
new_record = true;
last_record = rows.length - 1;
position = last_record + 1;
refreshDataControl();
}