redis hmget node.js async/await not working - javascript

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

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

How do I send the output of a function to a client in NodeJS?

I am working on a web interface based on NodeJS for my dumb printer. In my project, there is a feature which sends all the print jobs which are currently being processed. I obtain this information using lpstat (CUPS' status command). This executes whenever there is a GET request, as you can see here:
const express = require('express');
const { exec } = require('child_process')
var currentJobs;
function getCurrentJobs() {
exec("lpstat", (error, stdout, stderr) => {
if (error) {
optimisedOutput = "An error occurred : " + `${error}`;
} else if (stderr) {
optimisedOutput = "An error occurred : " + `${stderr}`;
}
currentJobs = `${stdout}`
console.log(currentJobs)
return currentJobs;
})
}
app.get('/currentJobs', (req, res) => {
currentJobs = getCurrentJobs()
currentJobs = JSON.stringify(currentJobs)
res.status(200).send(currentJobs)
console.log(currentJobs);
})
But, the variable currentJobs does not update. Instead, I get an undefined error and Postman does not show any outputs. It only shows the status code.
Please tell me what I'm doing wrong here.
Edit: This will all be running on a Raspberry Pi 3 connected to the printer which is why I'm using CUPS.
Your using exec as async execution, you either gonna need to change it to sync(prefer not to, for performance) or wrap it with promise, Ill show you the promise solution.
const express = require('express');
const { exec } = require('child_process')
var currentJobs;
async function getCurrentJobs() {
return new Promise((resolve) => {
exec("lpstat", (error, stdout, stderr) => {
if (error) {
optimisedOutput = "An error occurred : " + `${error}`;
} else if (stderr) {
optimisedOutput = "An error occurred : " + `${stderr}`;
}
currentJobs = `${stdout}`
console.log(currentJobs)
resolve(currentJobs);
})
})
}
app.get('/currentJobs', async (req, res) => {
currentJobs = await getCurrentJobs()
currentJobs = JSON.stringify(currentJobs)
res.status(200).send(currentJobs)
console.log(currentJobs);
})
I think it will be better if you just promisify the function and use it as async/await as it will be much more readable and you are making a asynchronous call and expecting the behaviour of the code in a synchronous manner
const express = require("express");
const { exec } = require("child_process");
const app = express();
app.listen(9999, () => {
console.log("started");
});
function getCurrentJobs() {
return new Promise((resolve, rejects) => {
exec("lpstat", (error, stdout, stderr) => {
if (error) {
console.log("An error occurred : " + `${error}`);
rejects(error);
} else if (stderr) {
console.log("An error occurred : " + `${stderr}`);
rejects(stderr);
}
const currentJobs = `${stdout}`;
console.log(currentJobs);
resolve(currentJobs);
});
});
}
app.get("/currentJobs", async (req, res) => {
const currentJobs = await getCurrentJobs();
res.status(200).send(currentJobs);
console.log(currentJobs);
});
Try using this, it will help you.
You'll have to return a promise otherwise getCurrentJobs() is not returning anything
const express = require("express");
const { exec } = require("child_process");
function getCurrentJobs() {
return new Promise((resolve, rejects) => {
exec("lpstat", (error, stdout, stderr) => {
if (error) {
console.log("An error occurred : " + `${error}`);
rejects(error);
} else if (stderr) {
console.log("An error occurred : " + `${stderr}`);
rejects(stderr);
}
const currentJobs = `${stdout}`;
console.log(currentJobs);
resolve(currentJobs);
});
});
}
app.get("/currentJobs", async (req, res) => {
try {
const currentJobs = await getCurrentJobs();
console.log(currentJobs);
}
catch(err) {
res.status(500).send(err);
}
});

Consuming external API from Hapi js server on startup not returning a promise

I am new to Hapi and I want to consume an API when the server starts up. I on start-up I am getting "Error: handler method did not return a value, a promise, or throw an error."
I came across this post and was trying to model my code after the answer supplied here, but it is not working, even though I am returning the promise from the fetch.
Here is my server.js.
"use strict";
var Hapi = require("#hapi/hapi");
var Request = require("request");
const Inert = require("#hapi/inert");
const Vision = require("#hapi/vision");
//Init server
const init = async () => {
const server = Hapi.server({
port: 3000,
host: "localhost",
routes: {
cors: true,
},
});
await server.register(Vision);
await server.register(Inert);
// await server.register(require("vision"));
server.route(require("./routes/getapis").getapis);
await server.start();
console.log(`Server is running on ${server.info.uri}`);
};
process.on("unhandledRejection", (err) => {
console.log(err);
process.exit(1);
});
init();
This is my getApis.js
const fetch = require("node-fetch");
const spendingApiUrl = `https://opendata.maryland.gov/resource/gja3-vy5r.json?$select=vendor_zip,sum(amount)&$where=vendor_zip between '20601' and '21930'&$group=vendor_zip&$order=sum_amount DESC`;
const numberOfTopZips = 3;
let results = [];
let marylandData = [];
exports.getApis = {
method: "GET",
path: "/getapis",
handler: (request, h) => {
return fetch(spendingApiUrl)
.then((response) => response.json())
.then((data) => {
marylandData = data;
console.log(marylandData);
//rateLimitedRequests(topZips(marylandData, numberOfTopZips));
})
.catch((err) => console.log(err));
},
};

How to use promise in JS and Node JS

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

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

Categories

Resources