Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot read property 'typeCast' of undefined mysql

I have the code:

import { createConnection } from 'mysql';
import { promisify } from 'util';

export default class Database {
    static instance: Database;

    query;
    db;

    constructor(user, password, database, host) {
        Database.instance = this;

        this.db = createConnection({ user, password, database, host });
        this.db.connect();
        this.query = promisify(this.db.query);
    }

    async getUser(id: number, filter: string = null) {
        return this.query('SELECT * FROM users WHERE id = ' + id)
        .then((err, res, fields) => {
            return res[0];
        });
    }
}

and an express route passing the id to getUser.

When this code is executed, I get this stack.

(node:16544) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(node:16544) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'typeCast' of undefined
    at Database.query (<project>\node_modules\mysql\lib\Connection.js:199:34)
    at Database.query (internal/util.js:232:30)
    at Database.getUser (<project>\lib\structures\Database.js:13:21)
    at get (<project>\lib\api\routes\user.js:5:33)
    at Layer.handle [as handle_request] (<project>\node_modules\express\lib\router\layer.js:95:5)
    at next (<project>\node_modules\express\lib\router\route.js:137:13)
    at Route.dispatch (<project>\node_modules\express\lib\router\route.js:112:3)
    at Layer.handle [as handle_request] (<project>\node_modules\express\lib\router\layer.js:95:5)
    at <project>\node_modules\express\lib\router\index.js:281:22
    at param (<project>\node_modules\express\lib\router\index.js:354:14)
(node:16544) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 6)

How do I resolve this?

like image 335
Cole Avatar asked Jan 29 '18 22:01

Cole


2 Answers

I found a different solution to the same problem. I haven't tested your code with this, but looking at the source code of the mysql module, in my case this was no longer correct. Binding query to the db object fixes it for me. In your case that would look like this: this.query = promisify(this.db.query.bind(this.db));

like image 191
Jake Avatar answered Oct 22 '22 19:10

Jake


Promisify(...) returns a promise. So you should use await like so: await Promisify(...)

The solution would be:

1) Remove the this.query = promisify(...) and this.db.connect(); lines from your constructor

2) Your Database class and getUser functions should look like this:

export default class Database {
    static instance: Database;

    static async getInstance(user?, password?, database?, host?) {
        // all arguments above are optional

        if(!Database.instance){
            const connection = createConnection({ user, password, database, host });
            await connection.connect();
            const dbQuery = await promisify(this.promisify(connection.query));
            Database.instance = {
                query: dbQuery 
            }
            return Database.instance;
        }
        return Database.instance;
    }

    static getUser(id: number, filter: string = null) {
        return Database.instance.query('SELECT * FROM users WHERE id = ' + id)
        .then((err, res, fields) => {
            return res[0];
        });
    }
}

To use:

Then, wherever you need:

async getUser(){
    let database = await Database.getInstance(); // or Database.getInstance(user, password ...)  to first initialize and then get the instance.
    return database.getUser(1234, filter);
}
like image 43
raneshu Avatar answered Oct 22 '22 21:10

raneshu