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?
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));
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With