Redis Client del function not being called inside a for loop - javascript

I have been trying to call the redisClient.del function inside a for loop and the function is not returning any state.
studentSchema.methods.generateAuthToken = function () {
let admin = this;
let access = 'student';
let token = jwt.sign({ _id: student._id.toHexString(), access }, HRCSECRET).toString();
student.tokens.forEach(element => {
console.log(element.token);
redisClient.del(element.token, (err, result) => {
if(err){
console.log(err);
}
else{
console.log(result);
}
})
});
student.tokens = [{ access, token }];
return student.save().then(() => { return token; });
};
There is no console.log statement printed during the execution

Did you try to check in Redis-cli is your stuff deleted?
Just a little refactor below
studentSchema.methods.generateAuthToken = async () => {
// your code before
const promises = []
student.tokens.forEach(element => {
promises.push(redisClient.del(element.token))
})
await Promise.all(promises)
// your next code
}

Related

Class in Nodejs does not return expected value when using parameter

I have a class on my node server, each function of it returns something from another api, the first function that I will show does not use a parameter, it returns the items correctly, the second that uses the Make parameter, does not return anything, and does not point out error
function getInventory:
(this function works normally)
async getInventory() {
try {
let res = await axios.get(URL);
let data = res.data;
return data;
} catch (err) {
return err;
}
}
function getMakesNew(make): (this function works without errors but does not return anything)
async getMakesNew(make) {
try {
let res = await axios.get(URL);
let data = res.data;
let count = 0;
while (data != make) {
if (data[count].ID === make) {
return data[count].Name;
} else {
count++;
}
}
} catch (err) {
return err;
}
}
Calling the two functions on the routes:
// GetInventory
routes.get('/getInventory', async (req, res) => {
return res.json(await Vehicle.getInventory());
});
// getMakesNew
routes.get('/getMakesNew/:make', async (req, res) => {
let { make } = req.params;
return res.json(await Vehicle.getMakesNew(make));
});
function getMakesNew returns:
{}
return keyword is missing from your second function

Dealing with nested forEach in Node.js

I am working on something that needs nested foreach loops in order to process some data.
Intention is there is an array of ID's I need to look up, each ID related to a user and I just need to extract their names from the response of an API call. Service A has the list of ID's and then sends a HTTP GET request to service B for each ID (can't change this), which then responds with the correct info in the format of
{
success: true,
user: {
name: 'John Doe'
}
}
Code that doesn't work but is my current code
incidents.forEach((name) => {
foo = {
nameID: names
}
const asyncForEach = async (array, callback) => {
for(let index = 0; index < array.length; index++) {
await callback(array[index], index, array)
}
}
const startMulti = async () => {
await asyncForEach(foo.nameID, async (obj, index) => {
await userController.userInfo(obj)
.then((userInfo) => {
foo.nameID[index] = userInfo.user.name
})
.then(() => {
foobarArray.push(foo)
})
})
return res.json({success: true, foobar: foobarArray})
}
startMulti()
})
Took the origional idea of nested foreach loops from this blog post which allowed me to do another before though this one won't work
https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404
edit show variables
let foo
let foobarArray = []
Added await to usercontroller now getting proper output but error message saying Cannot set headers after they are sent to the client
Names is coming from outside the code and is just needed where it is. Not sure how to explain it without explaining the project in whole/detail.
edit show code for usercontroller.userinfo
exports.userInfo = function(id) {
return new Promise((resolve, reject) => {
let user = {
_id: id
}
options.json = {user}
request.get('/userInfo', options, (err, response, body) => {
resolve(body)
})
})
}
This code work perfectly as expected - ie it sends request with proper payload and returns proper response.
Edit current code attempt
let foobarArray =[]
let names = []
let foo
for (const incident of incidents) {
foo = {
nameID: names
}
for (const id of incident.names) {
const userInfo = await userController.userInfo(id)
names.push(userInfo.user.name)
}
}
return res.json({success: true, fooreturned: foobarArray})
Error message caused by await in front of userController
SyntaxError: await is only valid in async function
edit attempt at making async function (I normally don't use async/await instead use promises)
Even after attempt code below it still gives the error message above - I had tried same code before I edited to show error message
exports.userInfo = async function(id) {
return new Promise((resolve, reject) => {
let user = {
_id: id
}
options.json = {user}
request.get('/userInfo', options, (err, response, body) => {
resolve(body)
})
})
}
Full code below except the userInfo function above which already is shown above.
exports.monitor = function(req, res, next) {
const fooID = req.params.id
let foobarArray =[]
let names = []
let foo
Incident.find({fooID})
.exec((err, incidents) => {
if(err) {
console.log(err)
return res.json({success: false, foobar: []})
}
if(incidents != []) {
for (const incident of incidents) {
foo = {
nameID: incident.foo[0].names
}
for (const id of foo.responded) {
const userInfo = await userController.userInfo(id)
names.push(userInfo.user.name)
}
}
return res.json({success: true, foobar: foobarArray})
}
})
}
That's pretty much the whole code except some logging lines I still have to add. I pretty much need the foobar: foobarArray to be an array of objects - foo - where nameID is the array of proper names not ID's. The proper names are fetched via the userController.userInfo where the ID is passed.
edit - New code after async and promisify - not sure I did the promisify correctly
exports.monitor = async function(req, res, next) {
const fooID = req.params.id
const incidents = await userController.incidentFind(fooID)
}
exports.incidentFind = async function(id) {
return new Promise((resolve, reject) => {
const sevenAgo = moment().subtract(7, 'days').toISOString()
let alertArray =[]
let names = []
let alert
Incident.find({monitorID, createdAt: {$gte: sevenAgo}})
.exec((err, incidents) => {
if(err) {
console.log(err)
return res.json({success: false, foobar: []})
}
if(incidents != []) {
for (const incident of incidents) {
foo = {
nameID: incident.foo[0].names
}
for (const id of foo.responded) {
const userInfo = await userController.userInfo(id)
names.push(userInfo.user.name)
}
}
return res.json({success: true, foobar: foobarArray})
}
})
})
}
Not sure what the actual controller monitor should contain. Bit lost
Error message
/home/me/Projects/app/incidents/controllers/users.js:100
const userInfo = await userController.userInfo(id)
^^^^^
SyntaxError: await is only valid in async function
Looks like the function should be async already (put async before function name).
I think you're looking for a simple
exports.monitor = async function(req, res, next) {
const fooID = req.params.id
const foobarArray = […]
const names = […]
try {
const incidents = await Incident.find({fooID}).exec()
for (const name of incidents) {
const foo = {
nameID: []
}
for (const userId of names) {
const userInfo = await userController.userInfo(userId)
foo.nameID.push(userInfo.user.name)
}
foobarArray.push(foo)
}
res.json({success: true, foobar: foobarArray})
} catch(err) {
console.log(err)
res.json({success: false, foobar: []})
}
}

How to get the result of async / await function?

I would like to return an object from the the async / await function A to pass it to another function.
Currently what I get as a result is Promise{ <pending> }' or undefined.
function A:
const parseRss = data => data.forEach(rssLink => {
const getFeed = async () => {
try {
const feed = await rssParser.parseURL(rssLink.rss);
const emailContent = {
emailBody: {
title: feed.title,
content: []
}
}
feed.items.forEach(item => {
feedObj.emailBody.content.push(`${item.title} : ${item.link}`)
});
return emailContent;
} catch (e) {
console.error(e);
}
};
return (async () => {
return await getFeed();
})();
});
Function B:
try {
const data = await getDataWithRss();
const emailData = await parseRss([{rss:'http://reddit.com/.rss'}]); // emailData is undefined
return formatEmail(emailData);
} catch (error) {
console.log(error);
}
How do I return emailContent from function A to use it in function B?
Thanks!
Since you made getFeed as async, no need another async. You are looping through, so return an array of promises. Once the you call use Promise.all to resolve. Since there could be multiple urls to fetch.
const parseRss = (data) =>
data.map((rssLink) => {
const getFeed = async () => {
try {
const feed = await rssParser.parseURL(rssLink.rss);
const emailContent = {
emailBody: {
title: feed.title,
content: [],
},
};
feed.items.forEach((item) => {
feedObj.emailBody.content.push(`${item.title} : ${item.link}`);
});
return emailContent;
} catch (e) {
console.error(e);
}
};
return getFeed();
});
try {
const data = await getDataWithRss();
const emailData = await Promise.all(parseRss([{rss:'http://reddit.com/.rss'}])); // emailData is undefined
return formatEmail(emailData);
} catch (error) {
console.log(error);
}
await will not work inside a forEach loop. Use a for...in loop instead.
actually, getFeed() is not necessary inside inner scope, you can use async in map callback:
const parseRss = data => data.map(async rssLink => {
const feed = await rssParser.parseURL(rssLink.rss);
const emailContent = {
emailBody: {
title: feed.title,
content: []
}
};
feed.items.forEach(item => {
feedObj.emailBody.content.push(`${item.title} : ${item.link}`)
});
return emailContent;
});

Variable Retains Original Value Despite Having New Value Earlier and Further within a Function

let getProjects = function() {
try {
return axios.get('https://app.asana.com/api/1.0/projects/')
} catch (error) {
console.error(error)
}
}
let getTasks = function(project) {
try {
return axios.get('https://app.asana.com/api/1.0/projects/'+project+'/tasks')
} catch (error) {
console.error(error)
}
}
async function getAsanaData() {
let projects = await getProjects()
projects = projects.data.data
projects.map(async (project) => {
//project.attachments = []
let tasks = await getTasks(project.gid)
if(tasks != undefined){
tasks = tasks.data.data
project.tasks = tasks
//console.log(projects)
}
})
console.log(projects)
return projects
}
Promise.try(() => {
return getAsanaData();
}).then((result) => {
//console.log(util.inspect(result, {showHidden: false, depth: null}))
//var asanaData = safeJsonStringify(result);
//fs.writeFile("thing.json", asanaData);
})
.catch(err=>console.log(err))
In getAsanaData(), projects has a new value after project.tasks = tasks.
However, it's original value is printed by console.log(projects) before return projects.
This of course also means that the original value rather than the necessary new value will be returned.
What is the cause and how do I resolve this?
Try this:
async function getAsanaData() {
let projects = await getProjects()
return Promise.all(projects.data.data.map(async (project) => {
let tasks = await getTasks(project.gid)
project.tasks = !!tasks ? tasks.data.data : project.tasks
return project
}))
}
This will go through the async calls to getTasks and return for each the project. Then you should get them all resolved via Promise.all

JavaScript Unable to get value returned from a then() call to another then() call

I am trying to execute this code:
UserSchema.methods.generateAuthToken = function () {
const user = this;
const access = 'auth';
const token = jwt.sign({_id: user._id.toHexString(), access}, 'abc123');
user.tokens.push({access, token});
user.save().then(() => {
return token;
});
};
In my express file, I have following code:
app.post('/users', (req, res) => {
const body = _.pick(req.body, ['email', 'password']);
const user = new User(body);
user.save().then(() => {
return user.generateAuthToken();
}).then((token) => {
res.header('x-auth', token).send(user);
}).catch((err) => {
console.log(err);
res.status(400).send(err);
});
});
The problem is that the token returned from the user.save().then() call in first file never reaches the express code user.generateAuthToken(). What is the reason and how should I solve it?
generateAuthToken has no return statement.
If you want to return the promise that then returns, then you have to do so explicitly.
you need to update your schema to the following:
UserSchema.methods.generateAuthToken = function () {
const user = this;
const access = 'auth';
const token = jwt.sign({_id: user._id.toHexString(), access}, 'abc123');
user.tokens.push({access, token});
user.save().then(() => {
return token;
});
};
The generateAuthToken does not return a Promise in your code

Categories

Resources