I'm using ES6 to build by Node.js app class. I want to create a db class, so I did the following :
"use strict"
var ini = require('node-ini');
var mysql = require('mysql');
let _db = new WeakMap();
// Class de base pour la base de donnée
class Db{
constructor () {
ini.parse('../config/settings.ini', function(err,data){
if(err) {
console.log(err);
return;
} else {
_db.set(this, mysql.createConnection({
host : data.database_MYSQL.host,
user : data.database_MYSQL.username,
password : data.database_MYSQL.password,
database : data.database_MYSQL.schema
}));
}
});
}
}
module.exports = Db;
It's the first I'm trying to store a private variable, and I looked on the web for solutions. I found the Weakmap solution that I tried to implement. But the MySQL connection won't store it with the following source code. I have this output :
_db.set(this, mysql.createConnection({
^
TypeError: Invalid value used as weak map key
at WeakMap.set (native)
at D:\supervision\application\class\db.js:15:21
at D:\supervision\application\node_modules\node-ini\node-ini.js:168:12
at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:380:3)
So how to deal with it ?
EDIT :
Here is how caller know when it's initialised :
var db;
function instantiateDb(callback){
db = new db_connector();
callback(db);
}
instantiateDb(function(db){
db.connectDatabase();
})
this is undefined inside the callback, it is not referring to an instance of Db, hence you get that error. Have a look at How to access the correct `this` inside a callback? for how to solve that.
However, there is a much bigger problem here: You are performing an asynchronous operation inside the the constructor. That means whatever wants to use an instance of Db has no way of knowing when it will be fully initialized.
A better way of solving this is to have a static asynchronous method that returns a new, fully initialized instance of Db:
class Db {
static get() {
return new Promise((resolve, reject) => {
ini.parse('../config/settings.ini', function(err,data){
if (err) {
reject(err);
} else {
resolve(new Db(data));
}
});
});
}
constructor (data) {
_db.set(this, mysql.createConnection({
host : data.database_MYSQL.host,
user : data.database_MYSQL.username,
password : data.database_MYSQL.password,
database : data.database_MYSQL.schema
}));
}
}
Which can then be used as
Db.get().then(db => {
db.connectDatabase();
});
Related
I've got an error in mediasoup-client while executing "device.createRecvTransport" in the Redux SAGA (I know this is not the best practice, but no choice).
"device.createRecvTransport" is actually an abstraction which holds a webRTC RTCPeerConnection instance. When I call it, it throws this error.
TypeError: Cannot read property '_createTransport' of null at createRecvTransport
the code:
function* createRecvTransport(device: Device) {
const {
id,
iceParameters,
iceCandidates,
dtlsParameters,
sctpParameters
} = yield sendRequest({
action: 'createWebRtcTransport',
data: {
forceTcp: false,
producing: false,
consuming: true
}
});
const recvTransport: Transport = yield call(device.createRecvTransport, {
id,
iceParameters,
iceCandidates,
dtlsParameters,
sctpParameters,
iceServers: []
});
}
the Device is declared with function
function* initDevice() {
const handlerName = detectDevice();
const device = new Device({
handlerName
});
const routerRtpCapabilities = yield sendRequest({
action: 'getRouterRtpCapabilities'
});
device.load({ routerRtpCapabilities });
}
"device.createSendTransport" method also works, the only issue is with creating Receive Transport. The method "router.createWebRtcTransport" get executed in the mediasoup router and it returns data before executing "createRecvTransport" in client side.
Seems the problem is with the "yield call" expression.
As the "device.createRecvTransport" isn't an async (handled with promise) function, it shouldn't be executed using "yield call".
When I removed "yield call", it fixed.
I've been making a discord.js bot following the official guide.
I have all my commands in the /commands folder as advised.
Then I followed the course to create a currency system with sequelize, following this page from the same guide.
I have a balance.js file inside the commands folder, but when I'm calling it, it gives me this error:
TypeError: currency.getBalance is not a function
I've defined the function in my app.js file, but how can I export it (or use it) inside the balance.js which is called by the app.js file?
This is the function defined in the main file app.js:
Reflect.defineProperty(currency, 'getBalance', {
value: function getBalance(id) {
const user = currency.get(id);
return user ? user.balance : 0;
},
});
This is balance.js:
module.exports = {
name: 'balance',
description: 'Informs you about your balance.',
cooldown : 10,
guildOnly : true,
aliases: ['bal', 'cur', 'gem', 'gems'],
execute(message, args) {
const Discord = require('discord.js');
const { Users, CurrencyShop, UserItems, CardBase, UserCollec } = require('../dbObjects');
const currency = require('../app.js')
async () => { const storedBalances = await Users.findAll();
storedBalances.forEach(b => currency.set(b.user_id, b));
UserCollec.sync(); }
const target = message.author;
return message.channel.send(`${target} has ${currency.getBalance(target.id)}<:Gem:756059891465977886>`);
},
};
EDIT:
I progressed. Now I understand that I have to import the currency variable, which has been declared as a new Discord.Collection() in app.js.
I need to refer to this variable in a module and this module doesn't seem to see it as a collection. How do I import it?
I would like to create one connection pool that every query will use. To do so, I've created a very simple class that assigns the connection pool to a member variable. The member variable is correctly set in the constructor, but when a member function is called that references the pool member variable, pool is null.
NOTE: I'm intentionally withholding credentials. Rest assured that it's correct on my end. :)
// Promise wrapper for MySQL driver
class Database {
constructor( connectionLimit = 10 ){
this.pool = mysql.createPool({
connectionLimit : connectionLimit,
host : 'XXX',
user : 'XXX',
password : 'XXX',
database : 'XXX'
});
console.log( this.pool ) // No problem!
}
query( sql, params ){
console.log( this.pool ) //UNDEFINED!!!!
// Irrelevant code removed
}
}
Now, if I define pool on the module level instead of in the class constructor, everything works as expected.
const pool = mysql.createPool({
connectionLimit : 10,
host : 'XXX',
user : 'XXX',
password : "XXX",
database : 'XXX'
});
// Promise wrapper for MySQL driver
class Database {
constructor( connectionLimit = 10 ){
console.log( this.pool ) // No problem!
}
query( sql, params ){
console.log( this.pool ) // No problem!
// Irrelevant code removed
}
}
In the first example, I expect this.pool to refernce the pool created in the constructor regardless of which member function is called. The second example does exactly what I would expect it to do.
This class is being used in an express API application. I'm creating an instance of Database, and then assigning a reference to the query method to the req object.
const db = new Database();
app.use( ( req, res, next ) => {
req.query = db.query // Pretty sure I'm borking up the context here
});
When you do
req.query = db.query
When req.query gets used later, it'll probably look something like:
req.query(parameters)
When the internal code calls callback, it calls it with the calling context of req, or with no calling context at all, if put into a standalone variable first; it's not called as a property of the object db object. So when the function is invoked, the this inside the callback does not refer to a particular database instance.
Another way to solve your problem without a module variable would be to pass a callback which itself calls .query with the proper calling context:
req.query = (...args) => db.query(...args);
Here is a simple express router, I want to give it query params and search the DB for them.
so, if the URL is like this api?x=value1 the app should query the DB for { x:value1 }
if the URL is api?x=value1&y=value2 the app should query the DB for { x:value1, y:value2 }
Since I don't know the number of params in advance, I have created an empty object and appended it with the params if existed.
if there are no params I want to retrieve all documents in DB.
.get(function (req, res){
let update_issue= {}; /*empty object*/
if(req.query.issue_title){update_issue["issue_title"] = req.query.issue_title}
if(req.query.issue_text){update_issue["issue_text"] = req.query.issue_text}
if(req.query.created_by){ update_issue["created_by"] = req.query.created_by }
/*append object if param exists*/
if(Object.keys(update_issue).length !== 0 ){ /*check if that object is not empty*/
db.collection('issues').find(update_issue, (err, data)=>{
res.json(data);
})
}
db.collection('issues').find().toArray((err, data)=>{
res.send(data);
})
this solution keeps giving me TypeError: Converting circular structure to JSON.
I understand that the object is in the form { x : "value" } and it should be JSON object like this { "x": "value" }
I tried flatted, JSON-stringify-safe still the same problem.
can you give me a solution to this problem, or an alternative way to continue the work.
I have solved the problem using node package called Api query params.
here is my code:
var aqp = require('api-query-params');
.get(function (req, res){
let update_issue= aqp(req.query);
if(Object.keys(update_issue).length !== 0 ){ /*check if that object is not empty*/
db.collection('issues').find(update_issue, (err, data)=>{
res.json(data);
})
}
db.collection('issues').find().toArray((err, data)=>{
res.send(data);
})
here is the package : https://www.npmjs.com/package/api-query-params
I'm trying to create an app using Loopback (V3) and i've encountered a weird error.
I'm trying to create my Mysql tables using autoupdate(), but for my custom models it is not working.
This is what i've tried so far ->
var server = require('../server');
var ds = server.dataSources.db;
var models = ['test','Post','User', 'AccessToken', 'ACL', 'RoleMapping', 'Role'];
ds.isActual(models, function(err, actual) {
if (!actual) {
ds.autoupdate(null, function(err,result){
console.log("DONE!");
console.log(result);
});
};
});
The script works. If the database is empty it will create tables for all EXCEPT test and Post. Those are my custom models, the others are built into loopback.
Is it because of model type? (tried Model and PersistedModel) or is it something else? I even tried without the isActual check and still nothing.
I would recommend that you keep two separate arrays for built-in models and custom models and write code like following, that way you could know where the issue is. also, I think there is an error in your code near ds.autoupdate(null, fun.....
please follow according to the below code
var builtInModels = ['AccessToken', 'ACL', 'RoleMapping','Role'];
var userDefinedModels = ['Post','test'];
// migrate built-in models
dataSource.isActual(builtInModels, function (err, actual) {
if (!actual) {
dataSource.autoupdate(builtInModels, function (err, result) {
if(err) console.log(err);
console.log('Datasource Synced: Built in models');
});
}
});
// migrate userdefined models
dataSource.isActual(userDefinedModels, function (err, actual) {
if (!actual) {
dataSource.autoupdate(userDefinedModels, function (err, result) {
if (err) console.log(err);
console.log('Datasource Synced: User defined models');
});
}
});