NodeJS nedb function not awaiting - javascript

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");
}
});
}

Related

Async | Can not get my async promise to function

I'm currently writing a login server function and I cannot figure out why the posmise that I'm making isnt being called
Im using mongodb with mongoose as the backend that is being connected to using the User.findOne which works. I cannot figure out why the bottom console.log for Test and test2 never get fired.
I'm quite new to the promise and async and I can't figure out what im missing
class HandlerGenerator {
login (req, res) {
console.log('debguh1')
let username = req.body.username;
let password = req.body.password;
let checkUsername = "";
let checkPassword = "";
var lData = {
username: req.body.username,
password: req.body.password
};
var myPromise = () => {
return new Promise((resolve, reject) => {
console.log('db2')
User.findOne(lData , function(err, userLogin){
if(err){
console.log(err);
return
}
console.log(userLogin)
checkUsername = userLogin.username;
checkPassword = userLogin.password;
});
});
};
var callMyPromise = async () => {
var result = await (myPromise());
// call code here
console.log("Test1")
resolve(result);
//return result
};
callMyPromise().then(function(result) {
console.log('Test2')
res.json(result);
});
}
}
I guess you are using mongoose for your queries, .exec() is returning a promise.
By making your login method async you can now await the response. But do make sure to wrap an await in a try catch block or HOF, to handle errors / or not found users.
class HandlerGenerator {
async login(req, res) {
let { username, password } = req.body;
let checkUsername = "";
let checkPassword = "";
var lData = {
username
password
};
try {
const userData = await User.findOne(lData).exec();
res.json(userData);
} catch (e) {
// do some error handling in here
}
}
}

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);
});

redis hmget node.js async/await not working

I am trying to get some data from redis through node.js using following code :
var moment = require("moment");
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var crypto = require('crypto');
var redis = require('redis');
var bluebird = require("bluebird");
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);
const uuidv4 = require('uuid/v4');
var KEY_USERS = "auction:users";
var KEY_ADMIN_TOKENS = KEY_USERS + ":admin_tokens";
var KEY_USER_TOKENS = KEY_USERS + ":user_tokens";
var SERVER_PORT = 12251;
var redis_client = bluebird.promisifyAll(redis.createClient({
host: '127.0.0.1',
no_ready_check: true,
auth_pass: '****',
}));
redis_client.on('connect', function () {
console.log('Redis client connected');
});
redis_client.on('error', function (err) {
console.log('Something went wrong with Redis Connection ' + err);
});
server.listen(SERVER_PORT);
console.log('1');
(async () => {
var response = await isAdminUser('c169024a-8902-4310-8955-ff46516e8703');
console.log("From Async " + response);
})()
console.log('2');
// Promise.resolve()
// .then(() => isAdminUser('c169024a-8902-4310-8955-ff46516e8703'))
// .then(() => console.log('3'));
console.log("Server Connected and redis initialized.");
async function isAdminUser(token) {
return new Promise((resolve, reject) => {
redis_client.hmget(KEY_ADMIN_TOKENS, [token, token], function (error, result) {
if (error) {
console.log(error);
throw error;
}
console.log("Token Result : " + result);
resolve(result);
});
});
}
Now the issue is, node is waiting for the redis query to complete and moving forward to the next line of code.
Output from the console :
1
2
Server Connected and redis initialized.
Redis client connected
Token Result : "my result"
From Async "my result"
Desired output :
1
2
Redis client connected
Token Result : "my result"
From Async "my result"
Server Connected and redis initialized.
What is it that I am missing / doing wrong ? I have gone through a lot of tutorials / articles suggesting the same.
Async functions are nothing more than a syntax sugar for functions that return promises, and it only makes sense to make a function async if you are using await in the function.
Your function isAdminUser doesn't use await, so it doesn't need async. It doesn't actually do anythin there.
Also, you are passing your redis_client to promisifyAll, but for this to have any effect you need to use the async methods in the client.
I refactored your code a little bit to move the client initialization to a promise:
const initializeRedisClient = () => new Promise((resolve, reject) => {
const redis_client = bluebird.promisifyAll(redis.createClient({
host: '127.0.0.1',
no_ready_check: true,
auth_pass: '****',
}));
redis_client.on('connect', function () {
console.log('Redis client connected');
resolve(redis_client);
});
redis_client.on('error', function (err) {
console.log('Something went wrong with Redis Connection ' + err);
reject(err);
});
});
(async () => {
const redis_client = await initializeRedisClient();
const response = await isAdminUser(redis_client, 'c169024a-8902-4310-8955-ff46516e8703');
console.log("From Async " + response);
console.log("Server Connected and redis initialized.");
})()
console.log('2');
async function isAdminUser(redis_client, token) {
const result = redis_client.hmgetAsync(KEY_ADMIN_TOKENS, [token, token]);
console.log("Token Result : " + result);
return result;
}

Error: Timeout of 2000ms exceeded. promise not returning before test runs

I am getting error of Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
This makes sense, if returning a promise to ensure it resolves, but I really thought that I do that already (by using the await keyword). There seems to be a race condition here that I don't understand
I am writing unit test for a database connection module:
states.js
const sqlite3 = require('sqlite3').verbose();
const util = require('util');
async function getDB() {
return new Promise(function(resolve, reject) {
let db = new sqlite3.Database('./project.db', (err) => {
if (err) {
console.error(err.message);
reject(err)
} else {
console.log('Connected to the project database.');
resolve(db)
}
});
return db
});
}
exports.getDB = getDB
try {
// run these statements once to set up the db
// let db = getDB();
// db.run(`CREATE TABLE services(id INTEGER PRIMARY KEY, service text, date text)`);
// db.run(`INSERT INTO services(id, service, date) VALUES (1, 'blah', '01-23-1987')`)
} catch(err) {
console.log(err)
}
exports.get = async function(service) {
function getResults(service) {
return new Promise(async function (resolve, reject) {
const db = await getDB();
let sql = `SELECT Id id,
Service service,
Date date
FROM services
WHERE service = ?`;
db.get(sql, [service], (err, row) => {
if (err) {
console.error(err.message);
reject(err)
} else {
if (row) {
let this_row = {'id': row.id, 'service': row.service, 'date': row.date};
this_row ? console.log(row.id, row.service, row.date) : console.log(`No service found with the name ${service}`);
resolve(this_row)
} else {
resolve(null)
}
}
})
});
}
let row = await getResults(service)
return row
}
exports.clear = async function(service) {
function deleteResults(service) {
return new Promise(async function (resolve, reject) {
const db = await getDB();
let sql = `DELETE from services
WHERE service = ?`;
db.run(sql, [service]);
});
}
await deleteResults(service)
}
my testStates.js:
const mocha = require('mocha');
const assert = require('assert');
const expect = require('chai').expect;
const should = require('chai').should();
const state = require('../state');
let deletion_sql = `DELETE from services WHERE service = ?`;
it("get() should return the expected row", async function() {
let db = await state.getDB()
await db.run(deletion_sql, 'blah')
await db.run(`INSERT INTO services(id, service, date) VALUES (1, 'blah', '01-23-1987')`)
let result = await state.get('blah')
console.log("get test result is")
console.log(result)
assert.deepEqual(result, { 'id': 1, 'service': 'blah', 'date': '01-23-1987' })
});
it("clear() should delete row from db", async function() {
await state.clear('blah')
let result = await state.get('blah')
assert.equal(result, null)
})
The test clear() should delete row fromdb` fails every time with the same error, it has not passed once. There is something fundamentally wrong with how I use these promises since I'm new to learning about promise in JavaScript.
I was able to get test running by using .then() instead of the await keyword:
it("clear() should delete row from db", async function() {
state.clear('blah').then(async function() {
let result = await state.get('blah')
assert.equal(result, null)
})
})
I am interested to find out why the await keyword didn't work here, since it worked in the other test; I would gladly accept that as answer.

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