数组长度报告不一致

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();
        }