How to pass data in a promise chain, I am using sequelize - node.js

I am really struggling here. Admittedly I am no guru especially when it comes to node and asynchronous programming, I am an old C# .net developer so I am comfortable with code but struggling here.
Here's the back story, short and sweet. I have a pg database and I am using the sequelize ORM tools to create a relatively simple CRUD app.
Here's what I want to do.
Make a call to the findAll function on one object.
I need a piece of information from that first call so that I can make a subsequent call.
For instance. Lookup the current user to get their details, grab their ID and now lookup their display preferences.
I know I can run two requests that are not linked using Promise.all, here is an example of this already working.
var delConfig = deliverabiltyConfigs.findAll2(req.signedCookies.tsUser);
var delPack = deliverabilityPackages.findAll2();
Promise.all([delConfig, delPack]).then((results) =>{
res.render('index', { title: 'Deliverability Calculator', UserEmail : req.signedCookies.tsUser, UserName : req.signedCookies.tsUserName, data:results[0], packs:results[1]});
});
Where I am stuck is passing data from one promise to then next and needing them to run asynchronously.
Please help!

There are a few way you can do this. Either use promise chaining or with async & await.
Promise chaining might be the simplest way to do this now, but I would suggest using async await as its easier to read. Since you didn't really provide a sample of what you were trying to do I will make something generic that should hopefully help.
So using promise chaining you would do something like:
pgConnection.findAll().then((data) => {
const foo = data.foo;
pgConnection.findSomething(foo).then((data2) => {
console.log(data2);
});
});
What is happening here is once the promise from findAll() is resolved successfully it will call the .then method and will pass the resulting data there for you to use in your next db query and then I am just printing out the result of the final db query.
This is how you could do it using async & await:
async function getFoo() {
const data = await pgConnection.findAll();
const foo = data.foo;
const data2 = await pgConnection.findSomething(foo);
console.log(data2);
}
The await keyword can only be used inside of an async function so it might not be as simple to change as just using a .then promise chain.

Related

Unable to find the source of error dialogflow fulfillment

I am trying to create intent in which when the user sends a parameter, then it should be checked in the database that is already there or not. If it already exists user gets a response A and if not it is added to the database, & the user gets response B. I am using Axios to make the API calls. But the code is not working.
I am getting a following errors in the console.
TypeError: Cannot set property 'response' of undefined
at axios.get.then.response (/srv/index.js:33:18)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)"
Show matching entries
Hide matching entries
Add field to summary line
I am not a professional, I am doing all this coding by learning from online tutorials and youtube videos Please help.
function idHandler(agent) {
const idcard = agent.parameters.idcard;
const idvalue = ' ';
const idname= ' ';
axios.get('API' + idcard)
.then(response => {
this.response = response.data;
idvalue = this.response[0].IDcard;
idname = this.response[0].Name;
});
if (idcard === idvalue) {
const ans = 'Name of ' + idname + ' is already present in the List';
agent.add(ans);
} else {
const data = [{
idcard: idcard
}];
axios.post('API', data);
}
}
You have a few issues with both how to code for Dialogflow, and how to express some of the syntax correctly. Some of that is because it looks like you're mixing code that expects Promises with code that doesn't.
The axios library is meant to work with Promises - the get and post methods both return Promises. So you can either work with them by using an await method, or by using the .then() method that the returned Promise has. You may want to look up details of both.
Additionally, Dialogflow requires that you either return the Promise, or that your handler be an async function (which will return a Promise for you).
If you're using the .then() approach, however, then everything you do that relies on the call to axios must be done inside the .then() block and you must return that Promise. If you use await, then your function must be declared as an async function. (You can probably mix the two - but don't.)
So that part of your code might look something like:
return axios.get( url )
.then( response => {
// Do EVERYTHING in here
});
And inside the then() code block is where you would extract the values you want, call agent.add() with the message, and possibly make the API call to add data.
While this didn't get flagged as an error, you are trying to assign a value to a const after it is initially set. This is an error. Those should probably be declared using let instead.
Your error looks like it is saying that this is undefined. Which seems... odd. But also not really an issue since you probably don't need to be using this for most of what you're trying to do. If you scope the variables with let, then they should be available for the life of the function.

ExpressJS - function returning undefinded

function checkFamilyStatus() keeps returning undefined for some reason, when it should be returning a boolean value from a mongodb collection.
A bit of context here - I decided to separate the logic part from the router methods like get and post methods, so as to make it look clean and understandable like in functional programming. So I put the logic part in functions and invoke them inside the router methods, but it doesn't work out. Besides, I don't know if this is a good practice or not. Wouldn't it be much easier to read if done like this, instead of say, putting a whole bunch of code in one place?
I've been stuck on this piece of code for a while. I am a bit confused on the working of asynchronous JS as a whole. I did some research, but still don't understand why this wouldn't work. Could someone clarify this up for me?
// post method
router.post("/create", ensureAuthenticated, async(req, res) => {
let userID = req.user.id;
console.log(await checkFamilyStatus(userID)); // but returns undefined
// rest of the code
}
// check family status
checkFamilyStatus = async userID => {
Account.findOne({
_id: userID
}, (err, account) => {
return account.hasFamily; // should return boolean value ?
});
};
Assuming the logic behind account.hasFamily is correct, then you need to await for the return, so it should be return await account.hasFamily;

pass result from AwaitReactions out of function discord.js

I am new to async functions. I want to utilize the code below to ask the user a question and react to the question with an X or check mark to get the users answer on whether or not to delete something to make room for a new entry.
The function below works perfectly fine. However, I want to pass the result from the function out of the function so I can make an if else statement outside of it and that is where I am stuck.
I've looked around online and saw several things related to callbacks being used, but each example I've seen is different for something I think is similar, so I am just confused. And none of these examples have been used for Reactions on Discord, so I'm just not sure where to go.
const agree = "✅"
const disagree = "❌"
let msg = await message.author.send("You have made the maximum number of decks. Would you like to delete one of your decks in order to make a new one? Please react with one of the following...")
await msg.react(agree)
await msg.react(disagree)
const filter = (reaction, user) => {
return ['✅', '❌'].includes(reaction.emoji.name) && user.id === message.author.id;
};
const reactions = await msg.awaitReactions(filter, {
max: 1
}).then(collected => {
const result = collected.last();
})
return result;
}
deleteDeckQuestion(function(result){
console.log(result)
}).catch(err => console.error(err))
The above code results in 'undefined' being logged to the console when I run deleteDeckQuestion. No errors otherwise. I would like it to make the Results variable accessible to me outside the function so I can make an if else statement based upon which reaction the user added to the question.
I tried putting the if else statement I wanted to use with the results of deleteDeckQuestion inside the async function and it operated fine, but then inside the "Yes" result of that function, I want to put another Async function to ask which deck 1, 2 or 3 should be deleted and have the same reaction-determines-answer-to-question scenario. Just saves the user typing more than necessary at the ease of mobile users.
Would it be easier I just put an async function inside another async function? Something tells me that isn't the best idea in terms of efficiency. Eventually these reactions will lead to using mysql queries, which I am comfortable with using, but it will get pretty lengthy and functions inside other functions just seems like a mess... not sure if that is part of the "callback hell" I've read the joys of though...
Thanks for any help in advance.
collected within your then() callback and reactions are the exact same object. However, result's scope is limited to within the callback.
In this example code, collected is the result of msg.awaitReactions(...)'s fulfilled promise. Then, result is declared in the same scope, and therefore accessible where you need it to be.
const collected = await msg.awaitReactions(filter, { max: 1 })
.catch(console.error);
const result = collected.first();
MDN: Async Programming, await, then(), scope
Discord.js: Message.awaitReactions()

How to return promise to the router callback in NodeJS/ExpressJS

I am new to nodejs/expressjs and mongodb. I am trying to create an API that exposes data to my mobile app that I am trying to build using Ionic framework.
I have a route setup like this
router.get('/api/jobs', (req, res) => {
JobModel.getAllJobsAsync().then((jobs) => res.json(jobs)); //IS THIS THe CORRECT WAY?
});
I have a function in my model that reads data from Mongodb. I am using the Bluebird promise library to convert my model functions to return promises.
const JobModel = Promise.promisifyAll(require('../models/Job'));
My function in the model
static getAllJobs(cb) {
MongoClient.connectAsync(utils.getConnectionString()).then((db) => {
const jobs = db.collection('jobs');
jobs.find().toArray((err, jobs) => {
if(err) {
return cb(err);
}
return cb(null, jobs);
});
});
}
The promisifyAll(myModule) converts this function to return a promise.
What I am not sure is,
If this is the correct approach for returning data to the route callback function from my model?
Is this efficient?
Using promisifyAll is slow? Since it loops through all functions in the module and creates a copy of the function with Async as suffix that now returns a promise. When does it actually run? This is a more generic question related to node require statements. See next point.
When do all require statements run? When I start the nodejs server? Or when I make a call to the api?
Your basic structure is more-or-less correct, although your use of Promise.promisifyAll seems awkward to me. The basic issue for me (and it's not really a problem - your code looks like it will work) is that you're mixing and matching promise-based and callback-based asynchronous code. Which, as I said, should still work, but I would prefer to stick to one as much as possible.
If your model class is your code (and not some library written by someone else), you could easily rewrite it to use promises directly, instead of writing it for callbacks and then using Promise.promisifyAll to wrap it.
Here's how I would approach the getAllJobs method:
static getAllJobs() {
// connect to the Mongo server
return MongoClient.connectAsync(utils.getConnectionString())
// ...then do something with the collection
.then((db) => {
// get the collection of jobs
const jobs = db.collection('jobs');
// I'm not that familiar with Mongo - I'm going to assume that
// the call to `jobs.find().toArray()` is asynchronous and only
// available in the "callback flavored" form.
// returning a new Promise here (in the `then` block) allows you
// to add the results of the asynchronous call to the chain of
// `then` handlers. The promise will be resolved (or rejected)
// when the results of the `job().find().toArray()` method are
// known
return new Promise((resolve, reject) => {
jobs.find().toArray((err, jobs) => {
if(err) {
reject(err);
}
resolve(jobs);
});
});
});
}
This version of getAllJobs returns a promise which you can chain then and catch handlers to. For example:
JobModel.getAllJobs()
.then((jobs) => {
// this is the object passed into the `resolve` call in the callback
// above. Do something interesting with it, like
res.json(jobs);
})
.catch((err) => {
// this is the error passed into the call to `reject` above
});
Admittedly, this is very similar to the code you have above. The only difference is that I dispensed with the use of Promise.promisifyAll - if you're writing the code yourself & you want to use promises, then do it yourself.
One important note: it's a good idea to include a catch handler. If you don't, your error will be swallowed up and disappear, and you'll be left wondering why your code is not working. Even if you don't think you'll need it, just write a catch handler that dumps it to console.log. You'll be glad you did!

Mongoose - Whats the difference between find({},cb) and find({}).exec(cb)?

I found 2 ways to execute queries using mongoose find(), but was wondering if they are different:
When should we use:
Model.find({},cb)
And when should we use:
Model.find({}).exec(cb)
Both execute the query and then run the callback.
The main difference is that the first one, returns a Query object while the second returns a Promise which is useful if you need promises.
const query = Model.find({}, cb);
Then you can work with the query variable.
While the promise...
const promise = Model.find({}).exec();
Then you can work with the promise and do things like:
promise.then(cb);
promise.catch((err) => {
console.error(err);
});
But if you do Model.find({}).exec(cb); the callback is also called without using promises...
I hope it helps
The difference is that the first one executes the query and calls your callback. Whereas in the second one where you omit the callback, the query will not be executed. Instead it will return a Query object which can be used to chain methods, specify search terms, and cursor options, etc...
http://mongoosejs.com/docs/2.7.x/docs/query.html
If you don't need to do any kind of chaining, or anything else with the underlying Cursor then just use the first method.
But the second method can be helpful to do things like:
findCars : function(options, callback) {
var query = Model.find({});
if(options.limit) query.limit(options.limit);
if(options.skip) query.limit(options.skip);
if(options.populate) query.populate(options.populate);
return query.exec(callback);
}

Resources