Trying to make a simple rest service. The rest service is for pulling up a table from a local database. This rest service a want to make available for an android app.
Having trouble getting passed .then block. Tried catching the error but with no success. How do you catch the error if it's going wrong in the first .then
The below piece of code is the db.js, and sets up the connection to the database.
var sqlDb = require("mysql");
var settings = require("../settings");
exports.executeSql = function (sql, callback) {
var conn = new sqlDb.createConnection(settings.dbConfig);
conn.connect()
// !! Error unhandled
.then(function () {
var req = new sqlDb.Request(conn);
req.query(sql)
.then(function (recordset) {
callback(recordset);
})
.catch(function (err) {
console.log(err);
callback(null, err);
});
})
.catch(function (err) {
console.log(err);
callback(null, err);
});
};
After setting up connection the below piece of code is executed. With error handling.
var db = require("../core/db");
exports.getList = function (req, resp) {
db.executeSql("SELECT * FROM employees", function (data, err) {
if (err) {
// throws back error to web
resp.writeHead(500, "Internal Error", { "Content-Type":
"application/json" });
resp.write(JSON.stringify({ data: "ERROR occurred:" + err }));
} else {
resp.writeHead(200, { "Content-Type": "application/json" });
resp.write(JSON.stringify(data));
}
resp.end();
});
};
Made a separated js file for settings such as database. Tested my connection to the db on a same way. Excluded that problem but it keeps returning an error unhandled on the first .then. I'm not familiar with methods till now.
I think I found the problem. new sqlDb.Request(conn); The .Request is not available when using mysql. But how can I fix this
If you catch() an error it will not be caught again without returning a new rejection. Like this:
conn.connect()
.then(function () {
var req = new sqlDb.Request(conn);
// note the "return" here
return req.query(sql)
.then(function (recordset) {
callback(recordset);
})
.catch(function (err) {
console.log(err);
callback(null, err);
// note the line below
return Promise.reject(err)
});
})
.catch(function (err) {
console.log(err);
callback(null, err);
});
};
PS. Do you really need the callback(), why not use the Promise?
Related
I'm facing an issue in my project I tried to do CRUD using MVC but when I run the code it doesn't return any data from db, the connection works fine I don't know why it doesn't work. I'm using NodeJS Express and mysql.
here is my code :
index.js:
db.connect(function(err) {
if (err) {
return console.error('error: ' + err.message);
}
console.log('Connected to the MySQL server.');
});
const usersRouter= require("./routes/routes");
app.use("/api/", usersRouter)
routes.js:
// get latest record of airMonitoring
router.get("/", airController.getAllData);
Model.js:
const AirMonitoring = function(table){
this.id = table.id;
this.Temperature = table.Temperature;
this.Humidity = table.Humidity;
this.AirCondition = table.AirCondition;
}
// get all data from airMonitoring
AirMonitoring.getAllData = ( result) =>{
db.query('SELECT * FROM AirMonitoring', (err, res)=>{
if(err){
console.log('Error while fetching airMonitoring', err);
result(err, null);
}else{
console.log('AirMonitoring fetched successfully');
result(res, null);
}
})
}
Controller.js:
exports.getAllData = (req, res)=> {
AirModel.getAllData((err, airMonitoring) =>{
if(err)
res.send(err);
console.log('data', airMonitoring);
res.send(airMonitoring)
})
}
and the error received from postman :
error Console :
You need to return your res call in your if (err) statement. If you don't add a return it will proceed to execute the codes that follows.
if(err) return res.send(err);
Then again, your error stemmed from something before this.
From my Model, I fetch some articles from a MySQL database for a user.
Model
var mysql = require('mysql');
var db = mysql.createPool({
host: 'localhost',
user: 'sampleUser',
password: '',
database: 'sampleDB'
});
fetchArticles: function (user, callback) {
var params = [user.userId];
var query = `SELECT * FROM articles WHERE userId = ? LOCK IN SHARE MODE`;
db.getConnection(function (err, connection) {
if (err) {
throw err;
}
connection.beginTransaction(function (err) {
if (err) {
throw err;
}
return connection.query(query, params, function (err, result) {
if (err) {
connection.rollback(function () {
throw err;
});
}
//console.log(result);
});
});
});
}
This is working and the function fetches the result needed. But it's not returning the result to the controller function (I am returning it but I'm not able to fetch it in the controller function. I guess, I did something wrong here).
When I did console.log(result) this is what I got.
[ RowDataPacket {
status: 'New',
article_code: 13362,
created_date: 2017-10-22T00:30:00.000Z,
type: 'ebook'} ]
My controller function looks like this:
var Articles = require('../models/Articles');
exports.getArticle = function (req, res) {
var articleId = req.body.articleId;
var article = {
userId: userId
};
Articles.fetchArticles(article, function (err, rows) {
if (err) {
res.json({ success: false, message: 'no data found' });
}
else {
res.json({ success: true, articles: rows });
}
});
};
Can anyone help me figure out what mistakes I made here?
I'm pretty new to nodejs. Thanks!
The simple answer is that you're not calling the callback function, anywhere.
Here's the adjusted code:
fetchArticles: function (user, callback) {
var params = [user.userId];
var query = `SELECT * FROM articles WHERE userId = ? LOCK IN SHARE MODE`;
db.getConnection(function (err, connection) {
if (err) {
// An error. Ensure `callback` gets called with the error argument.
return callback(err);
}
connection.beginTransaction(function (err) {
if (err) {
// An error. Ensure `callback` gets called with the error argument.
return callback(err);
}
return connection.query(query, params, function (err, result) {
if (err) {
// An error.
// Rollback
connection.rollback(function () {
// Once the rollback finished, ensure `callback` gets called
// with the error argument.
return callback(err);
});
} else {
// Query success. Call `callback` with results and `null` for error.
//console.log(result);
return callback(null, result);
}
});
});
});
}
There's no point in throwing errors inside the callbacks on the connection methods, since these functions are async.
Ensure you pass the error to the callback instead, and stop execution (using the return statement).
One more thing, without knowing the full requirements of this:
I'm not sure you need transactions for just fetching data from the database, without modifying it; so you can just do the query() and skip on using any beginTransaction(), rollback() and commit() calls.
I'm pretty new to Node and JS world. What I'm triyng to achieve is to "modularize" my queries and reuse them in various scenarios. This is my db manager:
'use strict'
const mysql = require('mysql')
var Promise = require('bluebird')
var using = Promise.using
Promise.promisifyAll(require('mysql/lib/Connection').prototype)
Promise.promisifyAll(require('mysql/lib/Pool').prototype)
const config = require('./config')
var pool = mysql.createPool({
connectionLimit: 100,
host: config.dbHost,
user: config.dbUser,
password: config.dbPassword,
database: config.db,
debug: config.dbDebug
})
var getConnection = function () {
return pool.getConnectionAsync()
.disposer(function (connection) {
return connection.release()
})
}
var query = function (command) {
return using(getConnection(), function (connection) {
return connection.queryAsync(command)
})
}
module.exports = {
query: query
}
In a separate file I want to call a query and depending on the result of that then call another one (the second one is using the result value of the first):
utils.method1()
.then(function (value) {
utils.method2(value)
})
.catch(function (error) {
console.error('Error while retrieving product id: ' + error)
res.json({ data: error })
})
How can I "promisify" my method? More importantly: is this the right way to separate mySQL queries? Can you suggest some best practices?
For completeness here's my method1 that execute the query:
module.exports = {
method1: function () {
// ...sql
db.query(mysql.format(sql, params))
.then(function (results) {
return results[0].id // clearly this is not a promise
})
.catch(function (error) {
console.error('Error while retrieving...: ' + error)
res.status(500).send('Internal server error')
})
}
}
You're actually very close from promisifying : )
Sure, results[0].id is not a promise, but it is the final value of one.
What you should do is return the chain of promises of your query :
return db.query(mysql.format(sql, params))
.then(function (results) {
return results[0].id // clearly this is not a promise
})
.catch(function (error) {
console.error('Error while retrieving...: ' + error)
res.status(500).send('Internal server error')
})
Doing so, you will return a promise that will either resolve with the last value of your chain, or fail. You can use it the way you asked:
method1.then(function(value){
// Here, value is results[0].id
})
.catch(function(err){
// Manage a failed query
});
There's a great post that you might want to read about how Promises works : https://blog.domenic.me/youre-missing-the-point-of-promises/
I am trying to get JSON from an API and store it into a MongoDB database.
Obviously, it doesn't work. My app seems to hang around the point where I try to save the data to the database. Please advise what to do.
Here's my code:
var express = require('express');
var router = express.Router();
var http = require('http');
var mongo = require('mongoskin');
var db = mongo.db("mongodb://localhost:27017/zak", {native_parser : true});
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
var site = 'http://www.vsechnyzakazky.cz/api/v1/zakazka/?format=json&limit=2';
function getData(cb) {
http.get(site, function(res) {
// explicitly treat incoming data as utf8 (avoids issues with multi-byte chars)
res.setEncoding('utf8');
// incrementally capture the incoming response body
var body = '';
res.on('data', function(d) {
body += d;
});
// do whatever we want with the response once it's done
res.on('end', function() {
try {
var parsed = JSON.parse(body);
} catch (err) {
console.error('Unable to parse response as JSON', err);
return cb(err);
}
// pass the relevant data back to the callback
cb(
parsed.objects
);
});
}).on('error', function(err) {
// handle errors with the request itself
console.error('Error with the request:', err.message);
cb(err);
});
}
function writeData (data, allGood){
// couple of visual checks if all looking good before writing to db
console.log('writing');
console.log(typeof data);
console.log(data);
db.collection('zakazky').save(data, function(error, record){
if (error) throw error;
console.log("data saved");
});
}
function allGood(){console.log('all done');}
getData(writeData);
// ---------------------
module.exports = router;
You are calling the save() instead of insert(). Change this part and it will work:
// this should call insert, not save
db.collection('zakazky').insert(data, function(error, record){
if (error) throw error;
console.log("data saved");
});
OK, so I have a problem. If an uncaught exception occurs while I am handling an HTTP request, I have no opportunity to call the end() method on the http.ServerResponse object. Therefore, the server hangs forever and never fulfills the request.
Here's an example:
var express = require('express');
var app = express.createServer();
var reqNum = 0;
app.get('/favicon.ico', function(req, res) {res.send(404);});
app.get('*', function(req, res, next) {
console.log("Request #", ++reqNum, ":", req.url);
next();
});
app.get('/error', function(req, res, next) {
throw new Error("Problem occurred");
});
app.get('/hang', function(req, res, next) {
console.log("In /hang route");
setTimeout(function() {
console.log("In /hang callback");
if(reqNum >= 3)
throw new Error("Problem occurred");
res.send("It worked!");
}, 2000);
});
process.on('uncaughtException', function(err) {
console.log("Uncaught exception!", err);
});
app.listen(8080);
If you visit /error, an exception occurs, but it is caught. The user receives an error message - no problem. If I visit /hang, though, the server will eventually throw an uncaught exception and hang forever. Any subsequent requests for /hang will hang.
This sucks. Any advice for how to fix this issue?
When an uncaught exception occurs, you're in an unclean state. Let the process die and restart it, there's nothing else you can do to safely bring it back to a known-good state. Use forever, it'll restart your process as soon as it dies.
If error is thrown synchronously, express won't stop working, only returning 500.
this.app.get("/error", (request, response) => {
throw new Error("shouldn't stop");
});
If error is thrown asynchronously, express will crash. But according to it's official documentation, there is still a way to recover from it by calling next:
this.app.get("/error", (request, response, next) => {
setTimeout(() => {
try {
throw new Error("shouldn't stop");
} catch (err) {
next(err);
}
}, 0);
});
This will let express do its duty to response with a 500 error.
Use try/catch/finally.
app.get('/hang', function(req, res, next) {
console.log("In /hang route");
setTimeout(function() {
console.log("In /hang callback");
try {
if(reqNum >= 3)
throw new Error("Problem occurred");
} catch (err) {
console.log("There was an error", err);
} finally {
res.send("It worked!");
}
}, 2000);
});