Search code examples
mysqlnode.jsjavascript-objects

Calling a function in a callback function in NodeJs


I am trying to implement this solution to my code. However, I am having trouble trying to call a function in a callback function.

In my index.js file, I have this

const db = require('./models/db.js');
db.connectDb();

In my db.js file, I have the following:

const mysql = require('mysql');

const database = {

    //Connects to the DB
    connectDb : function () {
        // Create connection 
        this.db = mysql.createConnection({
            host: 'localhost',
            user: 'root',
            password: '',
            database: 'example'
        });

        this.db.connect(function(err){
            if(err){
              console.log("An error has occured when trying to connect to db.");
              throw err;
            }
            console.log("MySQL Connected...");
        });

        this.db.on('error', function (err) {
            var currentdate = new Date();
            consoleoccurredn error has occured  @ ', currentdate,' with error:', err);
            if(err.code === 'PROTOCOL_CONNECTION_LOST') {
                this.handleDisconnect();
            } else {
                throw err;
            }
        });
    },

    handleDisconnect: function () {
        this.connectDb();
    }
}
module.exports = database;

The server starts up and MySQL connection has been successfully created. Since my intention is to handle the error connection lost, I restarted the server, and as expected, this.db.on('error', function (err) is executed, as reflected in the terminal.

MySQL Connected...
An error has occurred  @  [datetime]  with error: Error: Connection lost: The server closed the connection.
    at Protocol.end (/home/folder/node_modules/mysql/lib/protocol/Protocol.js:112:13)
    at Socket.<anonymous> (/home/folder/node_modules/mysql/lib/Connection.js:94:28)
    at Socket.<anonymous> (/home/folder/node_modules/mysql/lib/Connection.js:526:10)
    at Socket.emit (node:events:538:35)
    at endReadableNT (node:internal/streams/readable:1345:12)
    at processTicksAndRejections (node:internal/process/task_queues:83:21) {
  fatal: true,
  code: 'PROTOCOL_CONNECTION_LOST'
}

However, I get this error:

/home/folder/models/db.js:27
                this.handleDisconnect();
                     ^

TypeError: this.handleDisconnect is not a function
    at Connection.<anonymous> (/home/folder/models/db.js:27:22)
    at Connection.emit (node:events:526:28)
    at Connection._handleProtocolError (/home/folder/node_modules/mysql/lib/Connection.js:423:8)
    at Protocol.emit (node:events:526:28)
    at Protocol._delegateError (/home/folder/node_modules/mysql/lib/protocol/Protocol.js:398:10)
    at Protocol.end (/home/folder/node_modules/mysql/lib/protocol/Protocol.js:116:8)
    at Socket.<anonymous> (/home/folder/node_modules/mysql/lib/Connection.js:94:28)
    at Socket.<anonymous> (/home/folder/node_modules/mysql/lib/Connection.js:526:10)
    at Socket.emit (node:events:538:35)
    at endReadableNT (node:internal/streams/readable:1345:12)
[nodemon] app crashed - waiting for file changes before starting...

My question: Does this error have to do with trying to call a function outside of a callback function? Is it possible to call a function outside of a callback function, and that callback function is inside an object's function? Or is the problem something else?

For your reference, here is what is outputted in the terminal.

MySQL Connected...
An error has occurred  @  [datetime]  with error: Error: Connection lost: The server closed the connection.
    at Protocol.end (/home/folder/node_modules/mysql/lib/protocol/Protocol.js:112:13)
    at Socket.<anonymous> (/home/folder/node_modules/mysql/lib/Connection.js:94:28)
    at Socket.<anonymous> (/home/folder/node_modules/mysql/lib/Connection.js:526:10)
    at Socket.emit (node:events:538:35)
    at endReadableNT (node:internal/streams/readable:1345:12)
    at processTicksAndRejections (node:internal/process/task_queues:83:21) {
  fatal: true,
  code: 'PROTOCOL_CONNECTION_LOST'
}

/home/folder/models/db.js:27
                this.handleDisconnect();
                     ^

TypeError: this.handleDisconnect is not a function
    at Connection.<anonymous> (/home/folder/models/db.js:27:22)
    at Connection.emit (node:events:526:28)
    at Connection._handleProtocolError (/home/folder/node_modules/mysql/lib/Connection.js:423:8)
    at Protocol.emit (node:events:526:28)
    at Protocol._delegateError (/home/folder/node_modules/mysql/lib/protocol/Protocol.js:398:10)
    at Protocol.end (/home/folder/node_modules/mysql/lib/protocol/Protocol.js:116:8)
    at Socket.<anonymous> (/home/folder/node_modules/mysql/lib/Connection.js:94:28)
    at Socket.<anonymous> (/home/folder/node_modules/mysql/lib/Connection.js:526:10)
    at Socket.emit (node:events:538:35)
    at endReadableNT (node:internal/streams/readable:1345:12)
[nodemon] app crashed - waiting for file changes before starting...

Solution

  • The problem calling this.handleDisconnect() in this code:

        this.db.on('error', function (err) {
            var currentdate = new Date();
            if(err.code === 'PROTOCOL_CONNECTION_LOST') {
                this.handleDisconnect();
            } else {
                throw err;
            }
        });
    

    is that the value of this is not what you need it to be and that's why you get the error that this.handleDisconnect is not a function (it's probably undefined). A plain function callback will set its own value of this according to how the caller (which is your database) calls it. Instead, you can change it to an arrow function and it will retain the desired value of this. This is the main reason that arrow functions were invented (to preserve the lexical value of this):

        this.db.on('error', (err) => {
            var currentdate = new Date();
            if (err.code === 'PROTOCOL_CONNECTION_LOST') {
                this.handleDisconnect();
            } else {
                throw err;
            }
        });
    

    Another problem here is that throw err in this context will not be useful. You will throwing back into some asynchronous context in your database and that's not anywhere that you can catch or handle that error or do anything useful with it. So, you will need a more useful way to process that error.