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);
}
});
});
}
Related
I'm trying to get some data from a lot of URLs using 'request', but I can't manage to do it one url at a time.
I've tried to understand async/promises in order to make it work, but with no success. Trial and error didn't work.
I've seen other methods using different modules, but this requires rewriting most of my code and I believe there is an easier way to adapt it to my current code.
Here is a minimized version of the code :
const request = require('request');
const fs = require('fs');
const prod = fs.readFileSync('prod.txt', "utf8");
const prodid = prod.split("|");
var i;
var summary=[];
for (i=0;i<prodid.length;i++){
request('https://www.api.example.com/id='+prodid[i], { json: true }, (err, res, body) => {
if (err) { return console.log(err); }
if (body == 'NULL') {
console.log("Page " + i + " out of " + prodid.length + " is NULL!");
} else {
summary.push(body.items[0].Name);
summary.push(body.items[0].ISOnr);
summary.push(body.items[0].GTIN);
console.log("Page " + i + " out of " + prodid.length + " is done!");
fs.appendFileSync('data.txt',JSON.stringify(summary));
}
});
}
There is no async/promise involved in the example above, just the requests inside a loop.
From what I've seen, when I get the results, there is no particular order (probably is the order of which finishes first).
In the console, I always see page 500 out of 500, not 1/500, 2/500, etc.
What I'm trying to achieve, is by making each request in the order of URLs (preferably with a 1000ms delay between them)
You can promisify your request:
for (i = 0; i < prodid.length; i++) {
const result = await new Promise((resolve, reject) =>
request(
'https://www.api.example.com/id=' + prodid[i],
{ json: true },
(err, res, body) => {
if (err) {
reject(err);
}
if (body == 'NULL') {
console.log('Page ' + i + ' out of ' + prodid.length + ' is NULL!');
} else {
resolve(body);
}
}
)
);
if (result) {
summary.push(result.items[0].Name);
summary.push(result.items[0].ISOnr);
summary.push(result.items[0].GTIN);
console.log('Page ' + i + ' out of ' + prodid.length + ' is done!');
fs.appendFileSync('data.txt', JSON.stringify(summary));
}
}
As part of my project, I have to create text files which have to be downloaded as a ".txt".
I am using Node.js and React JavaScript, and I have already tried using the Node.js "fs.writeFile", but the browser doesn't recognize the download, the file name is always being called as the folder name and the file is always empty although the variable is a string and not empty.
I'm calling from the client to this function:
app.post("/downloadnetworks", async (req, res) => {
let selectedApps=req.body.selectedApps;
let arr=await sqlFunctions.createByIds(selectedApps);
res.send();
module.exports.createByIds = (productsArray) => {
return new Promise(function(resolve, reject) {
var bulkedString = '';
var product;
for (let obj of productsArray) {
let query = "select * from...........";
con.query(query, function(err, result, fields) {
if (err) throw err;
let stringifiedJson = JSON.stringify(result)
let parsedJson = JSON.parse(stringifiedJson)
The DB data is being added into the variable 'stringifiedJson', and it continues from here:
let parsedJson = JSON.parse(stringifiedJson) //has all the data from the DB
for (let network of parsedJson) {
if (network.certification_Id) {
bulkedString += network.domain_Name + ", " + network.publisher_Id + ", " + network.relationship + ", " + network.certification_Id;
} else {
bulkedString += network.domain_Name + ", " + network.publisher_Id + ", " +
network.relationship;
}
bulkedString += "\n";
product = network.product;
}
})
fs.writeFile('C:\Work\App ads.txt\App-Ads Files\'' + product + '.txt', bulkedString, 'utf8', (err) => {
if (err) throw err;
console.log('The file has been saved!');
});
}
resolve(bulkedString)
})
}
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);
}
I have a socket function defined as
var funcs = require('./funcs');
socket.on(EVENT_ACCEPT_ORDER, function(data, callback)
{
data = JSON.parse(data);
var bookingId = data.bookingId;
var userId = data.userId;
console.log("Accepting booking...." + bookingId);
var query = "UPDATE bookings SET bookingStatus = " + BOOKING_STATUS_ACCEPTED + " WHERE id = " + bookingId + " AND bookingStatus = " + BOOKING_STATUS_IN_QUEUE;
con.query(query, function(err, rows,fields)
{
if(err)
{
console.log("mysql query error");
}
else
{
if(rows.changedRows > 0)
{
var indexOfUser = usersList.indexOf(userId);
if(indexOfUser > -1)
{
userSockets[indexOfUser].emit(EVENT_USER_ORDER_ACCEPTED);
}
callback({"message": "Success","error":false, "booking": funcs.getBooking(con, bookingId)});
}
else
callback({"message": "Success","error":true});
}
});
});
Funcs is defined as
module.exports = {
"getBooking": function (con, bookingId)
{
var query = "SELECT * FROM bookings WHERE id = " + bookingId + " LIMIT 1";
con.query(query, function(err, rows,fields)
{
if(err)
{
console.log("mysql query error");
}
else if (rows.length == 1)
{
var booking = rows[0];
var userId = rows[0]['userId'];
var query = "SELECT id, name, phone, imagePath FROM users WHERE id = " + userId + " LIMIT 1";
con.query(query, function(err, rows,fields)
{
if(err)
{
console.log("mysql query error");
}
else if (rows.length == 1)
{
booking['user'] = rows[0];
return booking;
}
});
}
});
}
}
Everything is running fine except
callback({"message": "Success","error":false, "booking": funcs.getBooking(con, bookingId)});
in this function instead of booking, i am only getting
{"error":false,"message":"Success"}
Why am i not getting the booking function result?
You are not getting the result, because the result of the callback function in con.query is not returned to the caller of getBooking. It is the asynchronous pattern, which you are not processing correctly.
The way it is supposed to work is that the getBooking gets an extra argument: a function to be called when data are available (in an internal asynchronous call to con.query). Such a function is then provided by the caller and in this function you do whatever you want with the data:
funcs.js
"getBooking": function (con, bookingId, callback) {
...
con.query(query, function(err, rows,fields) {
...
// instead of return booking do
callback(err, booking);
...
}
}
main module
// instead of
callback({"message": "Success","error":false, "booking": funcs.getBooking(con, bookingId)});
// do
funcs.getBooking(con, bookingId, function(err, booking) {
callback({"message": "Success","error":false, "booking": booking});
});
I am afraid this is not the only issue in your code, but this should be the first to fix. Read further about processing asynchronous calls in general and specifically in node.js and fix other places in your code correspondingly.
I have a function getthem() that checks a mongo db for listings and returns name,streamurl for it.
I pass those as var stream to the renderme that renders the /dashboard page.
My problem is that i get the console.log("END OF FIND:"+JSON.stringify(stream))
to show my test input, but nothing goes to the render.
im using ejs to render. How can i get the result passed to the page ?
router.get('/dashboard', function (req, res) {
var foo = getthem();
function getthem() {
var group = "tesint";
console.log('geting for group : ' + group);
var mdlListings = require('../models/listings.js');
var myresult = "tet";
mdlListings.find({}, "name streamurl", function (err, data) {
if (err) {
console.error(err);
return;
}
if (data === null) {
console.log("No results");
return;
}
var stream = { };
data.forEach(function (streams) {
console.log("Got " + streams.name + " " + streams.streamurl);
stream[streams.name] = streams.streamurl;
// stream += 'name: '+streams.name+'},{streamurl: '+streams.streamurl;
// console.log("stram arry "+stream[streams.name] )
console.log("END OF FIND:"+JSON.stringify(stream))
}, renderme(stream));
// console.log("Result:", votes);
//var myresult = Object.keys(stream).map(function (name) {
// return { name: name, url: stream[name] };
//})
console.log("before return stream "+stream);
return stream;
});
}
function renderme(resa) {
console.log("RESA"+JSON.stringify(resa))
var resa = JSON.stringify(resa);
res.render('dashboard', {
title: 'Dashboard',
user: req.user,
listing: resa
}
)
}
You're passing the result of renderme(stream) as a second argument to forEach(). renderme(stream) is then evaluated immediately before your forEach() callback is called, when stream is still an empty object. My guess is you want something like this:
data.forEach(function (streams) {
console.log("Got " + streams.name + " " + streams.streamurl);
stream[streams.name] = streams.streamurl;
console.log("END OF FIND:"+JSON.stringify(stream))
});
renderme(stream);
Actually i figure that why would i pass the function as i could just do whatever i need to directly in there.
That worked perfectly, thanks for the tip.
data.forEach(function (streams) {
console.log("Got " + streams.name + " " + streams.streamurl);
stream[streams.name] = streams.streamurl;
});
res.render('dashboard', {
title: 'Dashboard',
user: req.user,
listing: data
}
)