'node.js + mysql: "Cannot enqueue Handshake after already enqueuing a Handshake."

I'm attempting to make two functions, one which retrives an object from an SQL database, the other which saves an object to the same SQL database. I am using node.js and mysql to do this. I have two functions, fetchEmployee and Employee.save, which fetch and save an employee respectively. When I call fetchEmployee, and the callback includes Employee.save, however, I get the error Cannot enqueue Handshake after already enqueuing a Handshake. Even weirder, Employee.save seems to run before the error is thrown.

EDIT: employee.save appearing to run is a symptom of async, as console.log("Saved!") is called before the callback function passed to SQL.parse This means the error appears during the parse. Further, if within parse console.log("connection created"); is added after con.connect, and console.log("Made it out."); is added after the end of con.connect, when calling Employee.save, the console outputs > "connection created", then throws the error, meaning the save query is never finished, but the error is thrown after con.connect

The Employee class is defined by the following

function Employee(obj) {
    /** Defines the Employee class
     * @arg obj.id : an integer; the employee's id
     * @arg obj.name : A string; the employee's name
     * @arg obj.position : A string; the employee's positions split by commas
     */

    this.id = obj.id;
    this.name = obj.name;
    this.position = obj.position;

    this.save = function() {
        SQL.parse({
            sql : `UPDATE EMPLOYEES
                SET id=?, name=?, position=?
                WHERE id=?`,
                replace_ : [this.id, this.name, this.position, this.id],
                result : false
        });
        console.log("Saved!");
    }
}

Note the console.log("Saved!");, as this comes up later

fetchEmployee is defined by this function:

function fetchEmployee(id, callback) {
    /** Fetch an employee from the employee table
     * @arg id : An integer; the id of the employee to fetch
     * @arg callback : A callback function to pass the employee to
     */

     SQL.parse({ // Perform the parse, define the sql, replace, and result
        sql : "SELECT * FROM employees WHERE id=?",
        replace_ : [id],
        result : true
     },

     function(err, data) {
         if(err) { // Pass an error if there's an error
             callback(err, null);
             throw err;
         }
         // Pass the employee to the callback as an employee object if there's no errors
         callback(null, new Employee({  // data is passed as a list from the sql table, so take only the object we need through [0]
                id : data[0].id,
                name : data[0].name,
                position : data[0].position
             })
         );
     });
}

Finally, SQL.parse is defined in this file:

var mySQL = require("mysql");

var con = mySQL.createConnection({ //Create connection
    host : "localhost",
    database : "testdb1",
    user : "root",
    password : "***************" 
});

function parse(obj, callback) {
    /** Parses an sql query. 
     * @arg callback : A callback function, will be passed the data
     * @arg obj.sql : an sql query
     * @arg obj.replace_ : A list of replacements for ?s in sql
     * @arg obj.result : a boolean indicating whether a result should be returned
     */

     //Assign meaningfull values
     obj.replace_ = obj.replace_ || [];
     callback = callback || function() {};

    con.connect(function(err) {
        if(err) throw err;

        //Connect and pass the sql command to the server
        con.query(obj.sql, obj.replace_, function(err, data) {
            if(err) { //Pass the err to the callback if there is an err
                callback(err, null);
                throw err;
            }
            else if(obj.result) { // Pass the data to the callback if result is true
                callback(null, data)
            }
        });
    });
}

module.exports = {
    parse : parse
};

When I call this block of code

fetchEmployee(985, function(err, data) {
    if(err) throw err;
    console.log(data);
    data.save();
});

The console outputs

Employee {
  id: 985,
  name: 'Skidd',
  position: 'Dishwasher, Busser',
  save: [Function] }
Saved!
Error: Cannot enqueue Handshake after already enqueuing a Handshake. [...]

It appears to me that it correctly runs fetchEmployee, as data is logged to the console correctly with the data of the employee. It then logs Saved!, seeming to indicate that Employee.save ran correctly, then after all the code is done, throws the error. I can't for the life of me figure out why this would happen, here or on google or through testing.

I've tried to add con.end to the end of parse in sql.js, this changes the error to Cannot enqueue Handshake after invoking quit



Solution 1:[1]

I was able to solve this problem by placing

var con = mySQL.createConnection({ //Create connection
    host : "localhost",
    database : "testdb1",
    user : "root",
    password : "***************" 
});

inside of the parse function, though I'm not 100% sure why this worked.

Solution 2:[2]

I followed what the previous person did and it worked for me too. I guess the problem was the connection was being made asynchronously. putting this inside the promise solved the problem

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Travis
Solution 2 Shweta Singh