Here is a snippet of transaction with node-mysql from the official github repo:
connection.beginTransaction(function(err) {
if (err) { throw err; }
connection.query('INSERT INTO posts SET title=?', title, function (error, results, fields) {
if (error) {
return connection.rollback(function() {
throw error;
});
}
var log = 'Post ' + results.insertId + ' added';
connection.query('INSERT INTO log SET data=?', log, function (error, results, fields) {
if (error) {
return connection.rollback(function() {
throw error;
});
}
connection.commit(function(err) {
if (err) {
return connection.rollback(function() {
throw err;
});
}
console.log('success!');
});
});
});
});
I feel there are too much boilerplates over here. Isn't there a more succinct way of making a transaction, like this?:
/* invalid code */
connection.beginTransaction();
const q1 = connection.query("SELECT 1;");
const q2 = connection.query("SELECT 2;");
const q3 = connection.query("SELECT 3;");
if (q1 && q2 && q3) {
connection.commit();
else {
connection.rollback();
}
It would be synchronous in this case though.
Related
I have this problem, although I managed the value of "result", the conditional expression "if" evaluates "result" always as "! == undefined" I also tried to manage with "result! == ''" but not handles it correctly. In this case I have no results from the sql query because "ricovero.cps" is not in the database and so I wrote some code to handle this case. How should I behave in order for the "if" to work correctly?
function getIdCPS(ricovero){
console.log("getIdCPS()");
querySQL = "SELECT id FROM codici_pronto_soccorso WHERE codice ='"+ricovero.cps+"'";
console.log("querySQL="+querySQL);
try{
connection.query(querySQL, function(err, result) {
if(err)
console.log(err);
if( result === undefined){
return "";
}else{
console.log("result is defined");
console.log("result=("+result+")");
return result[0].id;
}
});
}catch(e){
console.log("try/catch error:" + e);
}
}
Just put this code and monitor on console
const getIdCPS = (ricovero) => {
try {
const errorObj = { code: 400, error: 'Wrong Input' }
if (!ricovero || !ricovero.cps) {
throw errorObj;
}
const querySQL = "SELECT id FROM codici_pronto_soccorso WHERE codice ='" + ricovero.cps + "'";
connection.query(querySQL, (err, result) => {
if (err) {
throw err;
} else if (result) {
console.log(result);
return result;
} else {
throw err;
}
});
} catch (err) {
console.error(err);
throw err;
}
};
This is my code for logging in
method: 'POST',
path: '/api/login/sp',
config: { auth: false },
handler: function (request, reply) {
User.findOne({ phone: request.payload.phone }, function (err, user) {
if (err) throw err;
if (user !== null) {
user.comparePassword(request.payload.password, function (err, isMatch) {
if (err) throw err;
if (isMatch) { // Login success
data = {
"statusCode": 200,
"token": generateJWT(user._id)
}
return reply(data);
}
else {
reply(Boom.unauthorized('Invalid Account'))
}
});
}
else { // Invalid User
reply(Boom.unauthorized('Invalid Account'))
}
});
}
It takes a lot of code and makes it very hard to read. Is there a way to better write this part of the code so that it is easily maintainable and readable?
You may use return reply():
User.findOne({phone: request.payload.phone}, function (err, user) {
if (err) throw err;
if (user === null) return reply(Boom.unauthorized('Invalid Account'));
user.comparePassword(request.payload.password, function (err, isMatch) {
if (err) throw err;
if (!isMatch) return reply(Boom.unauthorized('Invalid Account'));
data = {
"statusCode": 200,
"token": generateJWT(user._id)
};
return reply(data);
});
})
Try using the return early pattern: Return early pattern for functions
User.findOne(..., {
// generic error
if (err) throw err;
// invalid user
if (user === null) {
reply(Boom.unauthorized('Invalid Account'));
return;
}
user.comparePassword(..., {
if (err) throw err;
if (!isMatch) {
reply(Boom.unauthorized('Invalid Account'));
return;
}
data = {
"statusCode": 200,
"token": generateJWT(user._id)
};
reply(data);
});
});
The following code is the same code used in the node-oracledb GitHub examples, called select1.js. I just modified it a little bit.
module.exports = function() {
var oracledb = require('oracledb');
var dbConfig = require('./dbconfig.js');
this.queryDB = function (query) {
oracledb.getConnection({
user : dbConfig.user,
password : dbConfig.password,
connectString : dbConfig.connectString
}, function(err, connection) {
if (err) {
console.error(err.message);
return;
}
connection.execute(query, function(err, result) {
if (err) {
console.error(err.message);
doRelease(connection);
return;
}
console.log(result.metaData);
console.log(result.rows);
doRelease(connection);
return result.rows
});
});
function doRelease(connection) {
connection.release(function(err) {
if (err) {
console.error(err.message);
}
});
}
}
}
This can be used as follow:
require('./dbquery.js')();
console.log(queryDB("SELECT * FROM users"));
I expected to see the same 2D matrix (representing the table) as on line "console.log(result.rows);". But the "console.log(queryDB("SELECT * FROM users"));" returns "undefined".
How can I return a value that I get in the callback function?
I tried to add a variable X at the beginning, like this:
module.exports = function() {
var oracledb = require('oracledb');
var dbConfig = require('./dbconfig.js');
this.queryDB = function (query) {
var X;
oracledb.getConnection({
user : dbConfig.user,
password : dbConfig.password,
connectString : dbConfig.connectString
}, function(err, connection) {
if (err) {
console.error(err.message);
return;
}
connection.execute(query, function(err, result) {
if (err) {
console.error(err.message);
doRelease(connection);
return;
}
console.log(result.metaData);
console.log(result.rows);
doRelease(connection);
X = result.rows
});
});
function doRelease(connection) {
connection.release(function(err) {
if (err) {
console.error(err.message);
}
});
}
return X;
}
}
But this is still undefined. How can I achieve this ?
It's running in async nature. You can resolve it with callback or promises. You can't get value like this.
pass the callback and return with callback
module.exports = function(callback) {//pass callback function and return with this
var oracledb = require('oracledb');
var dbConfig = require('./dbconfig.js');
this.queryDB = function(query,callback) {
oracledb.getConnection({
user: dbConfig.user,
password: dbConfig.password,
connectString: dbConfig.connectString
}, function(err, connection) {
if (err) {
console.error(err.message);
return callback(err);
}
connection.execute(query, function(err, result) {
if (err) {
console.error(err.message);
doRelease(connection);
return;
}
console.log(result.metaData);
console.log(result.rows);
doRelease(connection);
return callback(null, result.rows)
});
});
function doRelease(connection) {
connection.release(function(err) {
if (err) {
console.error(err.message);
return callback(err);
}
});
}
};
};
Currently I have the following callback system:
var saveTask = function(err, result) {
if (err) return callback(err, result);
var newid = mongoose.Types.ObjectId();
var task = new Task({
_id: newid,
taskname: req.body.name,
teamid: req.body.team,
content: req.body.content,
creator: req.user.userId
});
task.save(function (err) {
if (!err) {
log.info("New task created with id: %s", task._id);
return callback(null, task);
} else {
if(err.name === 'ValidationError') {
return callback('400', 'Validation error');
} else {
return callback('500', 'Server error');
}
log.error('Internal error(%d): %s', res.statusCode, err.message);
}
});
};
if (req.body.team) {
valTeam.isMember(req.body.team, req.user._id, function (err, done) {
if (err) {
saveTask('403', 'Not the owner or member of this team');
} else {
saveTask(null, true);
}
});
} else {
saveTask(null, true);
}
valTeam.isMember
exports.isMember = function(teamid, userid, callback) {
Team.find({'_id':teamid, $or:[{'creator': userid }, {'userlist': { $in : [userid]}}]}, function(err, result) {
if (err) return err;
console.log(result);
if (!result.length)
return callback('404', false);
else
return callback(null, true);
});
}
In short, if team is sent by POST, I'm checking if the user is member of that ID in valTeam.isMember. Am I using the correct syntax and best method to call back my saveTask function to save the task if the user is part of the team?
This code currently works, but I feel like there should be an easier way to do it? How could I use a promise to achieve the same thing?
Thanks in advance.
It's curious the fact that you create objects instead Schemas. However "every head is a different world", this is my way:
task.save(function(error, data){
if (error) {
trow error;
} else {
//Make whatever you want here with data
});
I have the following code:
var Company = function(app) {
this.crypto = require('ezcrypto').Crypto;
var Company = require('../models/company.js');
this.company = new Company(app);
}
// Create the company
Company.prototype.create = function (name, contact, email, password, callback) {
this.hashPassword(password, function(err, result) {
if (err) throw err;
console.log(this.company); // Undefined
this.company.create(name, contact, email, result.password, function(err, result) {
if (err) {
return callback(err);
}
return callback(null, result);
});
});
}
// Get company with just their email address
Company.prototype.hashPassword = function (password, callback) {
if(typeof password !== 'string') {
var err = 'Not a string.'
} else {
var result = {
password: this.crypto.SHA256(password)
};
}
if (err) {
return callback(err);
}
return callback(null, result);
}
module.exports = Company;
The problem is that this.company is undefined on line 11 of that code block.
I know this is not what I think, but I'm not sure how to refactor to get access to the correct this.
so theres 2 solution's to this
first the dirty one
Company.prototype.create = function (name, contact, email, password, callback) {
var that = this; // just capture this in the clojure <-
this.hashPassword(password, function(err, result) {
if (err) throw err;
console.log(that.company); // Undefined
that.company.create(name, contact, email, result.password, function(err, result) {
if (err) {
return callback(err);
}
return callback(null, result);
});
});
}
and the clean one using bind https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
Company.prototype.create = function (name, contact, email, password, callback) {
this.hashPassword(password, (function(err, result) {
if (err) throw err;
console.log(this.company); // Undefined
this.company.create(name, contact, email, result.password, function(err, result) {
if (err) {
return callback(err);
}
return callback(null, result);
});
}).bind(this));
}
You can reference this through another variable by declaring it in the Company.create scope, like this:
// Create the company
Company.prototype.create = function (name, contact, email, password, callback) {
var me = this;
this.hashPassword(password, function(err, result) {
if (err) throw err;
console.log(me.company); // Undefined - not anymore
me.company.create(name, contact, email, result.password, function(err, result) {
if (err) {
return callback(err);
}
return callback(null, result);
});
});
}
Untested, but it should work like this.