How to use promise in JS and Node JS - javascript

I have connected my sql server database to my nodejs application like this :
DAO.js
const sql = require('mssql')
class DAO {
constructor() {
this.sqlConfig = {user: 'connexionMartin', password: 'InfoMartin', server: '192.168.102.232\\SQLEXPRESS', database: 'PROFACE'}
}
async connect() {
try {
console.log("Connecting database.....");
let pool = await sql.connect(this.sqlConfig);
if (pool)
console.log("Database connected");
} catch (err) {
console.log(err);
}
}
async getDataLastHour() {
try {
let result = await sql.query('SELECT * FROM PROFACE.dbo.SuiviProduction WHERE Time_Stamp >= DATEADD(DAY,DATEDIFF(DAY,0,GETDATE()),0) AND DATEPART(HOUR,Time_Stamp) = DATEPART(HOUR,GETDATE())-1');
console.dir(result);
} catch (err) {
console.log(err);
}
}
}
app.js
const Server = require('./server/Server');
const DAO = require('./server/DAO');
const express = require('express');
const server = new Server();
const dao = new DAO();
server.start();
dao.connect();
Now I want to request my database using dao.getDataLastHour() in app.js, but the function is executed before application is connected to database. I have tried to fix this problem by using promise, like this :
const promise = dao.connect();
promise.then(dao.getDataLastHour());
But it doesn't seem to work.
Perhaps I don't use Promise correctly.

To use a then in you function,it need to return any result and turn it in a promise, or not use await, might it will work!
async connect() {
console.log("Connecting database.....");
sql.connect(this.sqlConfig).then(pool => {
if (pool)
console.log("Database connected");
}).catch (err{
console.log(err);
});
}
sorry for the bad identification!

Your method : dao.connect() does not return a promise.
So the first thing would be to change that method to return a promise which you can then listen to then decide whether to run a query or not. :
...
connect() {
return new Promise((resolve, reject) => {
try {
console.log("Connecting database.....");
let pool = sql.connect(this.sqlConfig);
if (pool)
console.log("Database connected");
resolve("Success");
} catch (err) {
console.log(err);
reject(err);
}
});
}
...
And then call your connect method like this:
dao.connect().then(
success => { ... }, // you can continue querying
error => { ... } // something went wrong
);
Also try to read a bit about how to use promises here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Differences between promise and async: What is the difference between JavaScript promises and async await?

You can try something like this:
connect() {
return new Promise((resolve, reject) => {
let pool = sql.connect(this.sqlConfig, function(err) {
if(!err) {
resolve();
}
else {
reject();
}
});
});
}
dao.connect().then(<<call function here>>)

Related

NodeJS nedb function not awaiting

Function checkExists is taking too long to execute. Tried to use await async function but had no effect. var exists = await checkExists(data.email); is returning undefined because not awaiting for checkExists.
I have my index.js:
const express = require('express');
const app = express();
require('./private/signUpAPI')(app);
app.listen(80, () => console.log('listening on 80'));
app.use(express.static('public'));
app.use(express.json({limit: '1mb'}));
And my signUpAPI.js:
const DataStore = require('nedb');
const express = require('express');
const database = new DataStore('private/database.db');
database.loadDatabase();
module.exports = function api(app){
app.use(express.json({limit: '1mb'}));
app.post('/signUpAPI', async (request, response) => {
console.log("Sign Up Request received!");
const data = request.body;
var exists = await checkExists(data.email);
console.log(exists)
console.log(data);
console.log("Added to DB");
console.log('-------------------------' + '\n');
database.insert(data);
const testData = {"status": "success"};
response.send(testData);
});
}
async function checkExists(email){
var exists = false;
database.find({"email": email}, async function(err, docs){
if (docs.length > 0){exists = true;}
console.log(docs.length);
return exists;
});
}
this is the node output when running index.js and calling the fetch('/signUpAPI'):
Sign Up Request received!
undefined
{
email: 'a',
username: 'a',
hashPass: 'da180265625ebeaf62f4ee1813bdc28faeaf79f0b2b329290758a1c095111ae8',
salt: 'g8VkTBV$+Bh35K9ns7Zt*9^CH#M=VELSzKUX=H3^+5kpFV=bEbVfXFtF*GGYHOa#'
}
Added to DB
-------------------------
37
I currently have 37 entries in the DB with the same data hence the console.log(docs.length) returning 37.
But this is executing last and appears at the bottom of the console when it should appear at the top.
Use https://www.npmjs.com/package/nedb-promise
so you can use await for database queries and you can change your code like this -
async function checkExists(email) {
const record = await database.findOne({ email });
console.log(record);
if (record) return true;
return false;
}
Functions you want to wait should return a promise in order to wait for response.
You either resolve the promise if the operation result is success or reject with an error.
The flow should like something like this;
async function func1()
{
try
{
var tmp = await func2();
console.log(tmp);
}
catch(err)
{
console.log(err);
}
}
async funcion func2()
{
return new Promise(async function (resolve, reject)
{
if(true)
{
resolve("success");
}
else
{
reject("error");
}
});
}

Promise returning undefined result to callback

I'm having issues with getting the result of a callback function. Below is the async function that I'm calling
const utils = {
sendQuery: async function(query){
// Receives a query and returns raw results
// Query is using default database specified by pool
// Returns a Promise
let conn;
try {
conn = await pool.getConnection();
let queryString = query;
let rows = await conn.query(queryString);
let results = (this.formatResults(rows));
console.log(results);
return results;
} catch(err) {
throw new Error(err);
} finally {
if (conn) return conn.end();
}
}
module.exports = {
'utils': utils
}
the console log above returns the expected result.
and below is the function that calls the above
const db = require('../private/db');
db.utils.sendQuery(queryString).then(function(result){
console.log(result);
}).catch(err=>{
throw res.render('error', {'error': err.stack});
})
the console log above returns undefined and I have no idea why.
The real problem here is this part if (conn) return conn.end();.
Whenever you are using finally, it will override any previous return, break, continue or throw that happens either in the stated try or catch blocks.
To fix your issue you should do like so:
const utils = {
sendQuery: async function(query){
// Receives a query and returns raw results
// Query is using default database specified by pool
// Returns a Promise
let conn;
try {
conn = await pool.getConnection();
let queryString = query;
let rows = await conn.query(queryString);
let results = (this.formatResults(rows));
console.log(results);
return results;
} catch(err) {
throw new Error(err);
} finally {
if (conn) conn.end();
}
}
module.exports = {
'utils': utils
}
Hope it works
In my opinion, just return results instead of resolve(results). Your function is already async and no promise object is created here.
And just throw err instead of reject(err);
And since you return in your try, you don't need your finally statement.
You need to simply return the result instead of calling resolve
const utils = {
sendQuery: async function(query){
// Receives a query and returns raw results
// Query is using default database specified by pool
// Returns a Promise
let conn;
try {
conn = await pool.getConnection();
let queryString = query;
let rows = await conn.query(queryString);
let results = (this.formatResults(rows));
console.log(results);
return results;
} catch(err) {
throw new Error(err)
} finally {
if (conn) return conn.end();
}
}
module.exports = {
'utils': utils
}
you could simply return or i suppose this is what you were trying to do
sendQuery: (query) => {
let promise = new Promise(async (resolve, reject) => {
let conn;
try {
conn = await pool.getConnection();
let queryString = query;
let rows = await conn.query(queryString);
let results = (this.formatResults(rows));
console.log(results);
resolve(results);
} catch (err) {
reject(err);
} finally {
if (conn) {
conn.end();
}
}
})
return promise;
}

Nodejs and Express, use res.send() from a worker thread

In Nodejs, using Express as a server, I offload a heavy computation onto a worker thread.
From the main application, I call the worker thread like this:
// file: main.js
const { Worker } = require("worker_threads");
function runService(fileName, workerData) {
return new Promise((resolve, reject) => {
const worker = new Worker(fileName, { workerData });
worker.on("message", resolve);
worker.on("error", reject);
worker.on("exit", code => {
if (code !== 0)
reject(new Error(`Worker stopped with exit code ${code}`));
});
});
}
router.get("/some_url", async function(req, res) {
const result = await runService(
"./path/to/worker.js",
{ query: req.query, user: req.user } // using { req } causes an error
);
});
The worker looks like this:
// file: worker.js
const { workerData, parentPort } = require('worker_threads');
const { query, user } = workerData;
async function run() {
const result = await generateLotsOfData(query, user);
parentPort.postMessage(result);
// What I would like to do here (doesn't work): res.send(result);
}
The worker generates a huge amount of data and "postMessage" causes a server error.
Is there a way to send this data from the worker thread directly to the client, using res.send() or something alike?
(instead of using postMessage and then sending from the main thread)?
It seems not possible to send directly from the worker-tread to the client.
In the end, I used child-process (instead of worker-treads), and send the result back to the main tread, and then to the client.
// file: main.js
var child_process = require('child_process');
// Run a worker thread
function runService(fileName, workerData) {
return new Promise((resolve, reject) => {
const worker = child_process.fork(fileName);
worker.on('message', function(message) {
if (message.ready) {
// worker is ready to receive data
worker.send(workerData);
} else {
// worker finished it's calculations, send the data to the client
resolve(message);
}
});
worker.on("error", function(x) {
console.log('error', x);
resolve({status: 500});
});
worker.on("close", function(y) {
console.log('close', y);
});
worker.on("exit", function(code) {
if (code == 0) {
console.log('report ran successfully');
} else {
console.log('report FAILED');
resolve({status: 500});
}
});
});
}
And in the worker:
process.on('message', run);
process.send({ready: true});
async function run(workerData) {
try {
const result = doSomeCalculations();
process.send({
data: JSON.stringify(result)
}, null, {}, function() {process.exit(0)});
} catch(err) {
console.error(err);
process.exit(1); // exit the process with a failure
}
}
// Make sure that this child_process doesn't accidentally stay in memory.
// Kill after 10 minutes. (not sure this is necessary, just to be sure)
setTimeout(function(){
console.log('Timeout in child-process');
process.exit(1);
}, 600000);
This actually works quite well.
This sample of code works :
create worker
create event handler
sendMessage --> wrapperWorkerThreadBigComputing
sendBack message on our main thread
emit server response
Api routes :
app.get('/bigComputingWithWorker', (req, res) => {
const worker = new Worker(`${__dirname}/src/wrapperWorkerThreadBigComputing.js`);
res.set('Content-Type', 'text/html');
worker.once("message", count => {
res.status(200).send(`The final count :${count}`);
});
worker.once("error", err => {
console.error(err);
res.status(400).send(`error worker thread`);
});
worker.postMessage({coucou : 'john'});
});
wrapperWorkerThreadBigComputing
const { parentPort } = require('node:worker_threads');
console.log("* worker created");
parentPort.once('message', (message) => {
let big = bigComputing();
parentPort.postMessage(big);
})
function bigComputing() {
let i = 0;
console.log("* start big computing")
for (i = 0; i < 300000000; i++) {
}
return i;
}

I called then() on a TypeScript promise but it is still pending. Why is this? How can I get it to resolve?

Here is the index.ts script I am running (based on something I found on reddit):
const path = require("path");
const sql = require("mssql");
const config = require(path.resolve("./config.json"));
let db1;
const connect = () => {
return new Promise((resolve, reject) => {
db1 = new sql.ConnectionPool(config.db, err => {
if (err) {
console.error("Connection failed.", err);
reject(err);
} else {
console.log("Database pool #1 connected.");
resolve();
}
});
});
};
const selectProjects = async (name) => {
const query = `
select * from [Time].ProjectData where [Name] like concat('%', concat(#name, '%'))`;
const request = new sql.Request(db1);
const result = await request
.input("name", name)
.query(query);
return result.recordset;
};
module.exports = {
connect,
selectProjects
};
connect().then(function() {
console.log(selectProjects('General'));
}).catch(function(err) {
console.log(err);
});
When I run the script using node index (after compiling it of course), I get this in the console:
Database pool #1 connected.
Promise { <pending> }
And then the script hangs.
Apparently the await keyword creates an implicit promise; I had to change the last function call to:
connect().then(function() {
selectProjects('General').then(function(data) {
console.log(data);
});
}).catch(function(err) {
console.log(err);
});

Async-await not working as anticipated. Value is 'undefined' after using await

I'm using socket.io with node js. For the authentication, I'm using middleware in socket.io but the code is not waiting for the middleware to finish its work thus the value is 'undefined'.
Here is the main function.
module.exports = async (server) => {
const io = require('socket.io')(server);
io.on(CONNECTION, async function (socket) {
var email = await authenticateUser(io);
console.log(email); // 'undefined'
user = new User(email);
});
}
Middleware function
async function authenticateUser(io) {
io.use(async (socket, next) => {
const handshakeData = socket.handshake.query;
const token = handshakeData.token;
const Email = await Token.isValid(token);
console.log("Auth ---> " + Email); // here it is fine
return new Promise((res, rej) => {
if (Email) {
res(Email);
} else {
rej();
}
});
});
}
Authtentication function
exports.isValid = async (token) => {
try {
const decoded = jwt.verify(token, JWT_KEY);
console.log(decoded.email) // here it is fine
return decoded.email;
} catch (error) {
return false;
}
}
Thank you!
The promise you are creating inside authenticateUser is not visible to the caller since it is created inside the scope of the function you are passing to io.use().
Instead, try creating the promise one lexical level higher so that it is visible after you are finished with the socket.io event handler:
// middleware function
function authenticateUser(io) {
return new Promise((resolve, reject) => {
io.use(async (socket, next) => {
const handshakeData = socket.handshake.query;
const token = handshakeData.token;
const Email = await Token.isValid(token);
if (Email) {
resolve(Email);
} else {
reject(); // should probably put an error here
}
});
});
}

Categories

Resources