jQuery выполняет части кода в неправильном порядке

#javascript #jquery #sqlite #electron

#javascript #jquery #sqlite #electron

Вопрос:

В настоящее время я работаю над проектом для моего дяди, который является ветеринаром. Это электронный проект, который позволяет ему управлять своими клиентами, пациентами и их посещениями. Однако после некоторого времени использования мы поняли, что иногда ipcRenderer срабатывает дважды или даже больше раз, когда пытается ввести нового клиента, пациента или назначить встречу. Я попытался уловить это, добавив еще один sql-запрос, который проверяет, есть ли идентичная запись к тому, что я хочу вставить, уже в базе данных. Теперь, однако, всякий раз, когда я пытаюсь вставить новую запись, db.all() (сначала был db.run(), я пытался исправить методом проб и ошибок в течение последних нескольких часов и отчаялся), который вставляет запись, выполняется перед db.all(), который получает количество идентичных записей и устанавливает счетчик, хотя он должен быть выполнен после. Я пытался исправить это с помощью $.when() и .done(), но затем столкнулся с проблемой невозможности проверить, равен ли счетчик 0, потому что .done() ожидает функцию, а .done(if) не работает. Кстати, я больше разбираюсь в C , java, C # и не очень хорошо знаком с jQuery, JS и тому подобным, так что извините, если моя ошибка тривиальна. Вот код, вы можете игнорировать эти длинные операторы SQL, я знаю, они не соответствуют соглашениям о кодировании, но они работают:

 $("#btn-ins-patient").on("click", function() {
        ipcRenderer.once('insert-patient', function(event, arg) {
                        
            let checksql = "select count(*) as 'zaehl' from patient where "
              "owner = "   arg.owner   " and name = '"   arg.name   "' and species = '"   arg.species   "' and breed = '"   arg.breed   "' and sex = '"   arg.sex   "' and neutered = '"   arg.neutered   "' and dead = '"   arg.dead   "' and chipnr = '"   arg.chipnr   "' and birthdate = '"   arg.birthdate   "'  and color = '"   arg.color   "';"

            db.all(checksql, function(error, rows) {
                if (error) {
                    console.log(error.code, checksql)
                    insertpatsql = "select * from patient where id = 1;";
                }
                else{
                    console.log(checksql);                      //second output in console, prints the right statement
                    for (let i = 0; i < rows.length; i  ) {
                        var counter = rows[i].zaehl;
                        console.log(counter);                   //third output in console, prints 0
                        setCount(counter);
                        console.log(cnter);                     //fourth output in console, prints 0 again
                    }
                    if(cnter != 0){
                        insertpatsql = "select * from patient where id = 1;";
                        console.log(insertpatsql);
                        console.log("double entry was stopped");
                    }
                    else{
                        
                        console.log(insertpatsql);              // fifth output in console prints the right statement (insert)

                    }
                    
                }  
            });

            let insertpatsql = "insert into patient"
              "(owner, name, species, breed, sex, neutered, dead, chipnr, birthdate, color, notes, diverse)"
              "values ('"   arg.owner   "', '"   arg.name   "', '"   arg.species   "', '"   arg.breed   "', '"   arg.sex   "', '"   arg.neutered   "', '"   arg.dead   "', '"   arg.chipnr   "', '"   arg.birthdate   "', '"   arg.color   "', '"   arg.notes   "', '"   arg.diverse   "');";

            if(cnter == 0){
                db.all(insertpatsql, function(error) {
                    if (error) {
                        console.log(error.code, insertpatsql)
                    }
                    else{
                        console.log(insertpatsql);
                        loadPatients();
                    }
                });
            }
            else{
                console.log("double entry was tried", insertpatsql, cnter);
                                                              //first output in console, cnter is undefined
            }
        })

        let child = new BrowserWindow({
            height: 485,
            width: 795,
            parent: parent,
            modal: true,
            resizable: false,
            show: false,
            webPreferences: {
                nodeIntegration: true
            }
        })

        child.loadFile('./ins/patient.html')

        child.once('ready-to-show', () => {
            child.show()
        })

        child.on('closed', () => {
            child = null
        })
    })
 

Это select * from patient where id = 1; просто из соображений безопасности, потому что иногда выполнялся второй db.all(), хотя этого не должно было быть. Я знаю, что мой код грязный, извините, я пытался исправить это весь день….

Вот как я устанавливаю cnter (глобальную переменную):

 var cnter;

function setCount(cnt){
    cnter = cnt;
}
 

Как мне убедиться, что checksql и его codeblock выполняются перед вставкой?

Комментарии:

1. вы имеете в виду, что первый запрос не завершен, а начинается второй запрос?

2. в принципе, да. Я не понимаю, как и почему это происходит. первый db.all() и if(cnter == 0) должны были бы запускаться почти одновременно. почему это не работает на протяжении всего первого блока, прежде чем начинать другой? или сначала он просто запускает вторую?

3. db.all не является асинхронным?

Ответ №1:

Хорошо, я думаю, что я исправил это, поместив второй блок внутрь первого. Это Код в том виде, в каком он есть сейчас:

 $("#btn-ins-patient").on("click", function() {
        ipcRenderer.once('insert-patient', function(event, arg) {
                        
            let checksql = "select count(*) as 'zaehl' from patient where "
              "owner = "   arg.owner   " and name = '"   arg.name   "' and species = '"   arg.species   "' and breed = '"   arg.breed   "' and sex = '"   arg.sex   "' and neutered = '"   arg.neutered   "' and dead = '"   arg.dead   "' and chipnr = '"   arg.chipnr   "' and birthdate = '"   arg.birthdate   "'  and color = '"   arg.color   "';"

            let insertpatsql = "insert into patient"
              "(owner, name, species, breed, sex, neutered, dead, chipnr, birthdate, color, notes, diverse)"
              "values ('"   arg.owner   "', '"   arg.name   "', '"   arg.species   "', '"   arg.breed   "', '"   arg.sex   "', '"   arg.neutered   "', '"   arg.dead   "', '"   arg.chipnr   "', '"   arg.birthdate   "', '"   arg.color   "', '"   arg.notes   "', '"   arg.diverse   "');";


            db.all(checksql, function(error, rows) {
                if (error) {
                    console.log(error.code, checksql)
                    insertpatsql = "select * from patient where id = 1;";
                }
                else{
                    console.log(checksql); //first output in console
                    for (let i = 0; i < rows.length; i  ) {
                        var counter = rows[i].zaehl;
                        console.log(counter); //second output in console
                        setCount(counter);
                        console.log(cnter); //third output in console
                    }
                    if(cnter != 0){
                        insertpatsql = "select * from patient where id = 1;";
                        console.log(insertpatsql);
                        console.log("double entry was stopped");
                    }
                    else{
                        
                        if(cnter == 0){
                            db.all(insertpatsql, function(error) {
                                if (error) {
                                    console.log(error.code, insertpatsql)
                                }
                                else{
                                    console.log(insertpatsql);
                                    loadPatients();
                                }
                            });
                        }
                        else{
                            console.log("double entry was tried", insertpatsql, cnter); //fourth output in console, cnter is undefinded
                        }

                    }
                    
                }  
            });
            
        })
})
 

Я не буду знать, работает ли это на самом деле, пока ipcRenderer не попытается выстрелить еще дважды. Как только я получу подтверждение, что это работает, я отмечу это.

Ответ №2:

Я не понимаю всего !!, Но это схема для цепочки транзакций базы данных

 function onSomeButtonClick()
{
  // The first query callback
  var firstQueryResults;
  var firstQuery = function(tx) {
    tx.executeSql(
      'SELECT * FROM databaseName WHERE greeting = "hello world"',
      [],
      function(tx, results) {
        firstQueryResults = results;
        return nextQuery(tx);
      });
  };

  var nextQuery = function(tx) {
    // Prepare something using firstQueryResults
    tx.executeSql('SOMETHING ELSE HERE',
      [],
      function(tx, results) {
        // Something good happens here
        return true; // Be sure to return false to roll back
      });
  };

  database.transaction(firstQuery, null, nextTransaction);
}

function nextTransaction() {
  // The next full transaction that's dependent on the
  // first transaction's data is called AFTER the first
  // transaction has completed.
}
 

Комментарии:

1. спасибо за ответ! Я получаю сигнал тревоги, но, за исключением этого, все остальное осталось прежним. Извините, если я странно сформулировал свой вопрос, я попытаюсь обобщить проблему: иногда, когда я пытался вставить запись, эта запись вставлялась дважды. Я огляделся и обнаружил, что это как-то связано с тем, что ipcRenderer выполняется более одного раза. Я пытался поймать это с помощью checksql, но теперь второй db.all() выполняется до завершения первого блока, что делает первый блок практически бесполезным, потому что код полагается на то, что checksql заполняет cnter перед вставкой.

2. предупреждение не завершает процесс, поэтому вы можете инициализировать setInterval для ожидания правильного значения checksql

3. я читаю db.all асинхронно, поэтому вы можете использовать .then() для выполнения следующего действия

Ответ №3:

Я бы заподозрил, что проблема заключается в том, что вы регистрируете обработчик событий внутри обработчика событий. В большинстве случаев обработчики событий должны быть зарегистрированы один раз в глобальной области видимости, а не в другом обработчике событий.

Я не понимал всего, что вы делали с этим счетчиком, но я думаю, что вы пытаетесь это сделать:

 ipcRenderer.on('insert-patient', function(event, arg) {
                
    let insertpatsql = "insert into patient"
      "(owner, name, species, breed, sex, neutered, dead, chipnr, birthdate, color, notes, diverse)"
      "values ('"   arg.owner   "', '"   arg.name   "', '"   arg.species   "', '"   arg.breed   "', '"   arg.sex   "', '"   arg.neutered   "', '"   arg.dead   "', '"   arg.chipnr   "', '"   arg.birthdate   "', '"   arg.color   "', '"   arg.notes   "', '"   arg.diverse   "');";

    db.all(insertpatsql, function(error) {
        if (error) {
            console.log(error.code, insertpatsql)
        }
        else{
            console.log(insertpatsql);
            loadPatients();
        }
    });
})

$("#btn-ins-patient").on("click", function() {

    let child = new BrowserWindow({
        height: 485,
        width: 795,
        parent: parent,
        modal: true,
        resizable: false,
        show: false,
        webPreferences: {
            nodeIntegration: true
        }
    })

    child.loadFile('./ins/patient.html')

    child.once('ready-to-show', () => {
        child.show()
    })

    child.on('closed', () => {
        child = null
    })
})
 

Комментарии:

1. Спасибо за предложение! Я знаю, что счетчик немного сбивает с толку, но мне пришлось определить его как глобальную переменную и создать set-функцию, иначе я не смог бы получить к нему доступ во второй области. В какой-то момент он был у меня внутри функции, но затем он не установил его, поэтому я сделал его глобальным. Оглядываясь назад, это, вероятно, было связано с тем, что кодовые блоки выполнялись в неправильном порядке, поэтому я понимаю, почему это сбивает с толку. Я также не лучший в кодировании в целом и, как правило, не отменяю ненужные изменения, которые я сделал при поиске ошибки, когда я пробую разные подходы…