I can't succeed into waiting an sql query result
This is what my Code looks like
socket.on('new', async function(information) {
console.log("check no offer en cours");
var checkOffer = "SELECT COUNT(*) as total FROM app__offer WHERE status_id = 1 AND profile_id = " + user.idUser;
doInsert = false;
con.query(checkOffer, function(err, result) {
if (err) throw err;
console.log(result[0].total);
if (result[0].total == 0) {
console.log("can insert");
doInsert = true;
}
}).then(function() {
console.log(doInsert);
if (doInsert) {
console.log("create offer");
var sql = "INSERT INTO app__offer (createdAt,updatedAt, startAt, programmed, startLatitude, startLongitude, commune_id, point_id, status_id,device,profile_id) " +
"VALUES ('" + todayDateTime + "','" + todayDateTime + "','" + todayDateTime + "'," + false + "," + user.latitude + "," + user.longitude + "," + user.idCommuneDestination + "," + user.idPoint + "," + 1 + "," + 'device' + "," + user.idUser + ")";
console.log(sql);
con.query(sql, function(err, result) {
if (err) throw err;
socket.emit('new', result);
});
} else {
console.log("Cet user a déjà une offre en cours");
}
});
Issue is the doInsert Log is executed before the canInsert Log.
I think that con.query() accept the callback and is also "thennable" returning a Promise.
In most cases if the callback is provided, that will be the handler of the result and it wont be passed to the Promise.
So
con.query(query, () => {
// this code is executed when the query ends
}).then(() => {
// this code is executed when the promise attached to .then() is resolved
// in this case con.query() is instant resolved cause a callback parameter is given
})
The solution is to put all in the callback OR all in the promise chain.
I would do like :-
try{
let result = await con.query(checkOffer);
if (result) {
let resultFromAnotherQuery = await con.query(sql);
if (resultFromAnotherQuery){
console.log("done");
}
}
}catch(err) {
console.log(err);
}
Related
I'm trying to insert an array of data into a table and this has to be done in a single go. I'm trying to implement a transaction with SQL Server in node js.
I can insert the data successfully, but the issue is whenever there is an error, the transaction is still getting committed. I know my code is not correct, can anyone help me correct my code?
saveStockbulkDetails = async(requestBody, res) => {
var toggle = true;
let dDate = new Date();
let currentDate = moment(dDate).format("YYYY-MM-DD");
const transaction = new sql.Transaction(dbconn1);
transaction.begin((err) => {
const request = new sql.Request(dbconn1);
for (let i = 0; i < requestBody.pipeDetails.length; i++) {
console.log(requestBody.pipeDetails[i].heat);
request.query(
"insert into JSULLCStockDB.dbo.ma_smallpipe_shipping_details(jsuordref, itemno, pipeid, heat, loadtallyno, uid_ent, tmstp_ent, date_ent)" +
" values('" +
requestBody.jsuOrder +
"'," +
"'" +
requestBody.itemNo +
"'," +
"'" +
requestBody.pipeDetails[i].pipeid +
"'," +
"'" +
requestBody.pipeDetails[i].heat +
"'," +
"'" +
requestBody.loadTallyNo +
"'," +
"'" +
requestBody.uid_ent +
"'," +
"getDate()," +
"'" +
currentDate +
"')",
(err, res) => {
if (err) {
transaction.rollback((err) => {
console.log("transaction commit rollback");
});
}
}
);
}
console.log(toggle);
if (toggle) {
transaction.commit((err) => {
if (err) {
console.log("transaction commit error!!");
} else {
console.log("transaction commit success!!");
}
});
}
});
}
hi everyone I tried to develop chat app using node js and socket.io for back end , my problem is empty value of associated array
socket.on('nickName', (data) => {
console.log(data)
var roomId;
con.query("SELECT user_id FROM nickname WHERE user_id = '" + String(data) + "'", (err, result) => {
if (err) {
throw err;
}
console.log(result)
if (result == undefined || result[0] == undefined) {
con.query("INSERT INTO nickname (user_id,socket_id) VALUES ('" + data + "','" + socket.id + "')")
} else {
con.query("UPDATE nickname SET socket_id = '" + socket.id + "' WHERE user_id = '" + data + "' ", (err, result) => {
})
}
})
con.query("SELECT * FROM room WHERE user_id = '" + data + "'", (err, result) => {
if(err){
throw err;
}else{
io.to(socket.id).emit('getChatList', { "chatList": result })
var unread = {}
result.forEach(Element=>{
roomId = Element.room_name
con.query("SELECT COUNT(*) FROM message WHERE room_id = '"+roomId+"' AND seen=0 AND to_user='"+data+"'",(err,unseen)=>{
if(err){
throw err;
}else{
// I trying set value to unread array
unread[roomId] =unseen[0]['COUNT(*)'] ;
// unread array work correctly
console.log(unread)
}
})
// problem is here print unread empty ({})in
// console.
console.log(unread)
})
}
})
});
unread array show empty value but when I put for example unread['A'] ='C' ; out of query block everything works fine , anyone can help me?
I solved my problem by using async.each() instead of result.forEach()
socket.on('nickName', (data) => {
console.log(data)
var roomId;
clients[data] = socket.id;
con.query("SELECT user_id FROM nickname WHERE user_id = '" + String(data) + "'", (err, result) => {
if (err) {
throw err;
}
console.log(result)
if (result == undefined || result[0] == undefined) {
con.query("INSERT INTO nickname (user_id,socket_id) VALUES ('" + data + "','" + socket.id + "')")
} else {
con.query("UPDATE nickname SET socket_id = '" + socket.id + "' WHERE user_id = '" + data + "' ", (err, result) => {
})
}
})
con.query("SELECT * FROM room WHERE user_id = '" + data + "'", (err, result) => {
if(err){
throw err;
}else{
io.to(socket.id).emit('getChatList', { "chatList": result })
var unread = {};
asyncc.each(result,function(Element,callbackk){
roomId = Element.room_name
console.log(Element)
con.query("SELECT COUNT(*) FROM message WHERE room_id = '"+Element.room_name+"' AND seen=0 AND to_user='"+data+"'",(err,unseen)=>{
if(err){
throw err;
}else{
console.log(unseen)
console.log(Element.room_name)
unread[Element.room_name] = unseen[0]['COUNT(*)'] ;
}
callbackk();
})
},function(er){
console.log(unread)
})
}
})
});
Every example I can find on sqlite3 and nodejs just writes the data to the console, which is useless - how do I await a data and return it from a calling method ? Lets say I have :
exports.selectData = function(tableName, parameters, successHandler) {
var dbConn = new sqlite3.Database('./data/myAppsData.db');
dbConn.all("SELECT " + parameters + " FROM " + tableName + "", function(err, rows) {
// what to do here ? or somewhere else ?
});
}
How do I get data (rows) to return from selectData ? Or alternatively, using successHandler callback ? (it is undefined where the comment is)
dbConn.all("SELECT " + parameters + " FROM " + tableName + "", function(err, rows) {
return rows // could replace with JSON.stringify(rows) If you want to pass JSON data
});
Or as ionizer said you could return a promise. If you need to use async/await
exports.selectData = function(tableName, parameters, successHandler) {
var dbConn = new sqlite3.Database('./data/myAppsData.db');
return new Promise((resolve, reject) => {
dbConn.all("SELECT " + parameters + " FROM " + tableName + "",
function(err, rows) {
if(err) {
reject (err);
} else {
resolve(rows);
}
});
});
}
Now i am working with Flipkart affiliate API and get the categories and products insert into my database.
I am using nodejs backend and postgresql database.
I used 4 async loop. But I done something but don't know the correct approach. Here I want to execute the loops in asynchronous and once all the process(loops) end means need to send response. How to I determine the all loops executed successfully. Please anyone suggest the correct approach.
var request = require('request');
var dateFormat = require('date-format');
var async = require('async');
router.get('/getproducts', function(req, res) {
var affiliateIdFrom = 1;
var affiliateUrl = "https://affiliate-api.flipkart.net/affiliate/api/<your affiliate_tracking_id>.json";
request(affiliateUrl, function(error, response, html) {
var resData = JSON.parse(html);
var dataObj = resData.apiGroups.affiliate.apiListings;
async.each(Object.keys(dataObj), function(item, done) {
var objData = dataObj[item].availableVariants['v0.1.0'];
var cname = objData.resourceName;
var curl = objData.get;
client.query('INSERT into product_category (affiliate_from, name, url,created_on) values (' + "'" + affiliateIdFrom + "'" + ',' + "'" + cname + "'" + ',' + "'" + curl + "'" + ',' + "'" + today + "'" + ')', function(err, result) {
if (err) {
console.log(err);
res.send({
data : "Soemthing went wrong",
});
}
done(err, result);
});
}, function(err) {
product.getProductDetails(affiliateIdFrom);
});
});
});
var product = {
getProductDetails : function(aId) {
var today = dateFormat(new Date());
client.query("select * from product_category where affiliate_from = " + aId + " limit 1", function(err, result) {
if (err) {
console.log(err);
}
var categoryList = result.rows;
async.each(categoryList, function(value, done) {
request.get({
headers : {
'Fk-Affiliate-Id' : 'XXXXX',
'Fk-Affiliate-Token' : 'XXXXXXXXXXXXXXXXXXXXXXX'
},
url : value.url
}, function(error, response, body) {
var data = JSON.parse(body);
var dataLength = data.productInfoList.length;
var dataObj = data.productInfoList;
if (dataLength > 0) {
async.each(dataObj, function(value1, done1) {
var productBasicInfo = value1.productBaseInfo.productIdentifier;
var productId = productBasicInfo.productId;
var productDetails = value1.productBaseInfo.productAttributes;
var pTitle = productDetails.title;
var thumbnailUrl = JSON.stringify(productDetails.imageUrls);
var category = productBasicInfo.categoryPaths.categoryPath[0][0].title;
var mrp = productDetails.maximumRetailPrice.amount;
var price = productDetails.sellingPrice.amount;
var prodcutUrl = productDetails.productUrl;
var productDescription = productDetails.productDescription;
if (productDescription != null) {
productDescription = productDescription.replace(/'/g, "\''");
}
var inStock = productDetails.inStock;
var information = JSON.stringify(value1);
var q = 'insert into product(affiliate_from, title, image_url, category_paths, mrp, price, url, description, in_stock, information, created_on) values (' + "'" + aId + "'" + ', ' + "'" + pTitle + "'" + ', ' + "'" + thumbnailUrl + "'" + ', ' + "'" + category + "'" + ', ' + "'" + mrp + "'" + ', ' + "'" + price + "'" + ', ' + "'" + prodcutUrl + "'" + ', ' + "'" + productDescription + "'" + ', ' + "'" + inStock + "'" + ', ' + "'" + information + "'" + ', ' + "'" + today + "'" + ' )';
console.log(q);
client.query(q, function(err, result) {
if (err) {
console.log(err);
} else {
console.log('inserted successfully');
}
});
done1("err", "result");
}, function(err) {
console.log('dddddddddd');
});
}
//console.log(data.productInfoList);
console.log(data.productInfoList.length);
done(err, "result");
});
}, function(err) {
console.log('doneeeeee');
});
});
}
};
The correct approach is to place each of your asynchronous requests inside a transaction, which when finished, will give you the indication of whether the whole set of queries was successful or not.
For example, using pg-promise syntax, your transaction would like this:
db.tx(function () {
return promise.all([
this.query("insert 1 ..."),
this.query("insert 2 ..."),
this.query("insert 3 ...")
]);
})
.then(function (data) {
// success;
}, function (reason) {
// error
});
I have the following Azure Mobile Services API get function. I want to set the isValidUser flag based on if there is a record for the providerKey (from the twitter authentication) in the SQLMembership table (AspNetUserLogins).
While testing, I see the following in the log file, confirming that the flag is being set.
"setting isValidUser [object Object] Number of records = 1"
However, if(isValidUser) is not getting evaluated correctly. The result I get from the API is "Not a registered user." which is set from the else portion of the if(isValidUser) check.
Why is it that the value set inside the mssql.query() is not available outside of it?
exports.get = function(request, response) {
var authenticatedUserId = request.user.userId;
var providerName = authenticatedUserId.split(":")[0];
var providerUserId = authenticatedUserId.split(":")[1];
var isValidUser = false;
console.log('providerName = ' + providerName.trim());
console.log('providerUserId = ' + providerUserId.trim());
request.service.mssql.query(
"select userId from dbo.AspNetUserLogins where LoginProvider = '" + providerName + "' and ProviderKey = '" + providerUserId + "'",
{
success: function(results)
{
console.log('inside success AspNetUserLogins. ' + results + " Number of records = " + results.length);
if (results.length == 1) {
console.log('setting isValidUser ' + results + " Number of records = " + results.length);
isValidUser = true;
}
},
error : function(err)
{
console.log('inside error AspNetUserLogins. ' + err);
response.send(statusCodes.INTERNAL_SERVER_ERROR, { error: err });
}
}
);
if (isValidUser) {
request.service.mssql.query('select * from dbo.Church',
{
success: function(results)
{
console.log('inside success Church' + results);
response.json(statusCodes.OK, results);
},
error : function(err)
{
console.log('inside error : ' + err);
response.send(statusCodes.INTERNAL_SERVER_ERROR, { error: err });
}
}
);
} else {
response.send(statusCodes.INTERNAL_SERVER_ERROR, { error: "Not a registered user." + isValidUser });
}
response.send(statusCodes.INTERNAL_SERVER_ERROR, { error: "Unexpected end." });
};
The call to mssql.query is an asynchronous function (like many other functions in node.js); when it returns the callback (either the success or the error) hasn't been executed yet, so when you check the isValidUser flag, it still has the original value (false).
What you need to do is to move that code to inside the success callback, and that should work:
exports.get = function(request, response) {
var authenticatedUserId = request.user.userId;
var providerName = authenticatedUserId.split(":")[0];
var providerUserId = authenticatedUserId.split(":")[1];
var isValidUser = false;
console.log('providerName = ' + providerName.trim());
console.log('providerUserId = ' + providerUserId.trim());
var sql = "select userId from dbo.AspNetUserLogins where LoginProvider = ? and ProviderKey = ?";
var sqlParams = [providerName, providerUserId];
request.service.mssql.query(sql, sqlParams, {
success: function(results)
{
console.log('inside success AspNetUserLogins. ' + results + " Number of records = " + results.length);
if (results.length == 1) {
console.log('setting isValidUser ' + results + " Number of records = " + results.length);
isValidUser = true;
}
if (isValidUser) {
request.service.mssql.query('select * from dbo.Church', {
success: function(results)
{
console.log('inside success Church' + results);
response.send(statusCodes.OK, results);
},
error : function(err)
{
console.log('inside error : ' + err);
response.send(statusCodes.INTERNAL_SERVER_ERROR, { error: err });
}
});
} else {
response.send(statusCodes.INTERNAL_SERVER_ERROR, { error: "Not a registered user." + isValidUser });
}
},
error : function(err)
{
console.log('inside error AspNetUserLogins. ' + err);
response.send(statusCodes.INTERNAL_SERVER_ERROR, { error: err });
}
});
};
One more thing: do use parameters in the SQL (also shown above), instead of composing the query directly. In this case (you're using the user id) it shouldn't be a problem, but as a general rule you should use parameters whenever possible to prevent SQL injection attacks.