Promise not working properly - javascript

I am trying to do a nested query with MySql, put the result inside a variable and send over http, but the program always run console.log("test 2:"+rpsData); before the query finish. I already tried this, but still getting the same problem.
const express = require('express')
const app = express()
const mysql = require('mysql');
const Connection = require('mysql/lib/Connection');
const Promise = require('bluebird');
Promise.promisifyAll([
Connection
]);
const connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'root123',
database : 'mygallery'
});
app.get('/posts', function(request, response) {
var rpsData;
connection.connectAsync()
.then(function() {
connection.query('SELECT * FROM post WHERE approved = 1', function(err, rows, fields) {
if (err) throw err;
rpsData = rows;
for (var i in rows) {
connection.query('SELECT * FROM image WHERE postCode = ?', [rpsData[i].postCode], function(err, rows, fields) {
if (err) throw err;
rpsData[i].image = rows;
console.log("test 1:"+rpsData);
});
}
});
})
.then(function() {
response.send(rpsData);
console.log("test 2:"+rpsData);
})
.catch(function(error) {
console.error('Connection error.', error);
});
});

What's happening here is you're not tying all of the pieces of async code to the promise chain. Once we convert it to do so this should work.
First lets wrap calls to connection.query to return a promise. We then have to return that generated promise to attach it to the outer promises chain.
If you don't return a promise, it won't know that it has to wait for your code to finish executing and will move forward with the next .then() statement on the outside promise (from connection.connectAsync);
You need to apply the same treatment to the inner query.
Sample code:
app.get('/posts', function(request, response) {
connection.connectAsync()
.then(function() {
return new Promise(function(resolve, reject) {
connection.query('SELECT * FROM post WHERE approved = 1', function(err, rows, fields) {
if (err) reject(err);
resolve(rows.reduce(function(accumulator, current) {
return accumulator.then(function(rpsData){
return new Promise(function(resolve, reject){
connection.query('SELECT * FROM image WHERE postCode = ?', [current.postCode], function(err, rows, fields) {
if (err) reject(err);
current.image = rows;
console.log("test 1:"+rpsData);
resolve(rpsData);
});
});
});
}, Promise.resolve(rows)));
});
});
})
.then(function(rpsData) {
response.send(rpsData);
console.log("test 2:"+rpsData);
})
.catch(function(error) {
console.error('Connection error.', error);
});
});
I'm queueing the internal promises using the technique I describe here

Related

Function: Select MySQL and Return JSON

Please help me, I need to implement a function in a separate module file and in the route where the render has to call this function receiving the query data:
function getSobre() {
return new Promise((resolve, reject) => {
db.query(`SELECT * FROM sobre ORDER BY cod DESC LIMIT 1`, (err, results) => {
if (err) {
return reject(err);
} else {
return resolve(results);
}
});
});
}
const data = {
title: getSobre().then(data => {
/*
* HERE How do I return this "data" to the "title:" ?????????????
*/
}),
name: 'Fabio',
profession: 'Analista'
}
module.exports = data;
db.query is a Js callback . Which will wait for the result , then return anything.
So data will always be empty since it is getting returned much before db.query getting full resolved
You should wrap this in a native promise, and then resolve the promise :
function getTabela{
return new Promise(function(resolve, reject) {
// The Promise constructor should catch any errors thrown on
// this tick. Alternately, try/catch and reject(err) on catch.
let sql = "SELECT * FROM sobre ORDER BY cod DESC LIMIT 1";
var data = {};
db.query(sql, (err, results, fields) => {
if (results.length > 0) {
resolve(fields)
} else {
console.log('Erro: ' + err);
}
});
});
}
getTabela().then(function(rows) {
// now you have your rows, you can see if there are <20 of them
}).catch((err) => setImmediate(() => { throw err; }));
This way you should always have the data which is expected out of the query.

Await is only valid in async functions

I'm trying to rewrite my code to incorporate promises. I know that mongo already incorporates promises but i'd like to understand promises a bit more first. I don't understand the error message because I have used await in the async function. I found this articles that seems to do it similarly, but I still wasn't able to get it working.
What am i doing incorrectly here?
error message
SyntaxError: await is only valid in async function
code
app.post('/search/word',urlencodedParser, async function(req, res){
try{
MongoClient.connect(url, { useNewUrlParser: true }, function(err, db) {
if (err) throw err;
let dbo = db.db("words");
//Declare promise
let searchWord = function(){
return new Promise(function(resolve, reject){
dbo.collection("word").find({"$text": {"$search": req.body.word}})
.toArray(function(err, result) {
err ? reject(err) : resolve(result);
});
});
};
result = await searchWord();
db.close();
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(result));
});
} catch(e) {
console.log(e);
}
});
The callback functions needs to be async
app.post('/search/word',urlencodedParser, async function(req, res){
try{
MongoClient.connect(url, { useNewUrlParser: true }, async function(err, db) {
if (err) throw err;
let dbo = db.db("words");
//Declare promise
let searchWord = function(){
return new Promise(function(resolve, reject){
dbo.collection("word").find({"$text": {"$search": req.body.word}})
.toArray(function(err, result) {
err ? reject(err) : resolve(result);
});
});
};
result = await searchWord();
db.close();
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(result));
});
} catch(e) {
console.log(e);
}
});

Why is rows(callback) function from db.all returning undefined while rows is defined?

I'm calling a function to see if an email adress is in the db. It's either an empty or filled array. Whenever i return this value it is undefined afterwards. How can I solve this? Thanks in advance!
I have tried using next() and promises.
The function that calls the db query function.
const emailExists = async function(req,res,next){
let emailInDb = await usermodel.getOneByEmail(req, next);
console.log(emailInDb);
if(emailInDb.length !==0){
res.send('email already in use!');
}
else{
return next();
}
};
The db query.
const getOneByEmail = function (req, next){
let db = new sqlite3.Database(dbPath, (err) => {
if (err) {
console.error(err.message);
}
console.log('Connected to books db.');
});
db.all(`SELECT * FROM users WHERE email = ?`, [req.body.email],
(err, rows) => {
console.log(rows);
return rows;
});
};
console.log(emailInDb) gives undefined.
While console.log(rows) gives an array with results.
Putting await in front of a non async function does not magically make the function wait for the db-calls to resolve. You need to wrap the db-calls in a promise, e.g:
const getOneByEmail = (req, next) => {
return new Promise((resolve, reject) => {
let db = new sqlite3.Database(dbPath, (err) => {
if (err) {
console.error(err.message);
reject(err);
}
console.log('Connected to books db.');
});
db.all(`SELECT * FROM users WHERE email = ?`, [req.body.email],
(err, rows) => {
// TODO: check for error here and reject
console.log(rows);
resolve(rows);
});
});
};
Note that you shouldn't connect to the database each time you call getOneByEmail, instead reuse the connection...

Node.js await postgresql error

I use express and PostgreSql.
My Project Folder :
-Model
-Visitor.js
-app.js
I have connected postgresql with pg and i've tested with a query. It's running well. But, there is a query on Visitor.js file.
var visitor = function() {
this.add = function() {
var ret = false;
db.query({text: 'INSERT INTO visitor(visitorid, data, status) VALUES($1, $2, $3)', values:[id, JSON.stringify(data), "1"]}, function (err, response) {
if(!err) {
ret = true;
}
});
return ret;
}
}
This query always inserts a row in my table but returns false. This function should wait query to end. How can i do it ?
You should await on a promise
this.add = function() {
return new Promise((resolve, reject) => {
db.query({text: 'INSERT INTO visitor(visitorid, data, status) VALUES($1, $2, $3)', values:[id, JSON.stringify(data), "1"]}, function (err, response) {
if(!err)
resolve(response)
else
reject(err)
});
})
}
Then you can await on visitor.add function
EDIT
If you are using the pg library: as shown in Getting Started, you can directly await on the client.query function as it returns a Promise when you don't provide a callback
const { Client } = require('pg')
const client = new Client()
await client.connect()
const res = await client.query('SELECT $1::text as message', ['Hello world!'])
console.log(res.rows[0].message) // Hello world!
await client.end()

Pass object from SQL query function to a separate function [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I'm new to node and promises. I have two files - server.js and db.js
server.js imports db.js as modules.
I'm fetching some data from a SQL database in a db.js module and I'm trying to pass that data to a function in server.js.
I've successfully fetched the data from database, but when I try to pass it to the function in server.js, it only returns an undefined value.
Here's the code
server.js
const db = require('./db.js');
app.post('/api/trigger-push-msg/', function (req, res) {
return getSubscriptionsFromDatabase()
.then(function(subscriptions) {
// Do something
});
});
function getSubscriptionsFromDatabase() {
return new Promise((resolve, reject) => {
let subscriptions = db.getSubscriptions();
console.log(subscriptions); // this only prints "undefined"
if (subscriptions != undefined) {
resolve(subscriptions);
} else {
reject("No"); // this executes
}
})
}
db.js
module.exports = {
getSubscriptions: function() {
var sql = "SELECT * FROM subscriptions";
con.query(sql, function(err, result) {
if (err) throw err;
console.log(result); // this prints the same result as I want
return result;
})
}
}
getSubscriptions doesn't have a return statement
and considering that there's some async content in it you should wrap all inside a promise and trigger the subsequent logic only after it resolves.
module.exports = {
getSubscriptions: function() {
var sql = "SELECT * FROM subscriptions";
return new Promise(function(resolve, reject){
con.query(sql, function(err, result) {
if (err) return reject(err);
resolve(result);
})
})
}
}
then:
function getSubscriptionsFromDatabase() {
return db.getSubscriptions()
.then(function(subscriptions){
return subscriptions;
})
}
and in your route:
app.post('/api/trigger-push-msg/', function (req, res) {
getSubscriptionsFromDatabase()
.then(function(subscriptions) {
res.send(subscriptions);
})
.catch(function(err){
res.sendStatus(500);
})
});

Categories

Resources