Static Promise.resolve()/reject() is always interpreted as resolve() - javascript

I'm using the following two pieces of code :
Store.addUser(newUserInfo).then(function(firstResult) {
Store.getUserList().then(function(result){
console.log('this side');
console.log(result);
io.sockets.emit('userAdded', {
userMapByUserId: result
});
}, function(error) {
console.log('List of users could not be retrieved');
console.log(error);
io.sockets.emit('userAdded', {
userMapByUserId: []
});
}
);
}, function(rejection) {
socket.emit('userNotAdded', {
userId: -1,
message: rejection.reason,
infoWithBadInput: rejection.infoWithBadInput
});
});
and in Store :
var addUser = function(newUserInfo) {
var validationResult = Common._validateUserInfo(newUserInfo);
if (validationResult.isOK) {
return keyValueExists('userName', newUserInfo.userName).then(function(userNameAlreadyExists) {
if (userNameAlreadyExists) {
validationResult = {
isOK: false,
reason: 'Username already exists',
infoWithBadInput: 'userName'
};
return Promise.reject(validationResult);
} else {
var newUserId = generateUserId();
//TODO: change it somehting more flexible. e.g. a predefined list of attributes to iterate over
var newUser = {
'userName': newUserInfo.userName,
'password': newUserInfo.password,
'userId': newUserId,
'lastModificationTime': Common.getCurrentFormanttedTime(),
'createdTime': Common.getCurrentFormanttedTime()
};
var user = new User(newUser);
user.save(function(err) {
if (err) {
console.log(err);
console.log('There is a problem saving the user info');
return Promise.reject('There is a problem saving the user info');
} else {
console.log('A new user added: ');
console.log(newUser);
//return getUserList();
return Promise.accept(newUser);
}
});
}
});
} else {
return Promise.reject(validationResult);
}
};
But in the first code , when I do Store.addUser(newUserInfo) it always runs the first function (resolve function) which shouldn't be the case if we do return Promise.reject() in addUser. Any idea on why this happens ?

You've got two return statements too few, two too much, and are overlooking a non-promisified function call.
Store.addUser(newUserInfo).then(function(firstResult) {
return Store.getUserList().then(function(result){
// ^^^^^^
…
This one is not really problematic, as you don't chain anything after the resulting promise, but it shouldn't be missed anyway.
…
return keyValueExists('userName', newUserInfo.userName).then(function(userNameAlreadyExists) {
if (userNameAlreadyExists) {
…
} else {
…
var user = new User(newUser);
user.save(function(err) { … });
// ^^^^
}
});
In this then-callback, you are not returning anything from your else branch. The promise is immediately fulfilled with undefined, and the ongoing save call is ignored - your promises don't know about it, so they can't await it. That's why Store.getUserList() that follows next in the chain doesn't see the changes; they're not yet stored.
It's also the reason why your Promise.reject inside that callback is ignored, and why Promise.accept never caused any problems.
You will need to create a new promise for the result of the save invocation here (so that you actually can return it):
…
var user = new User(newUser);
return new Promise(function(resolve, reject) {
user.save(function(err) {
if (err) {
console.log(err);
console.log('There is a problem saving the user info');
reject('There is a problem saving the user info');
} else {
console.log('A new user added: ');
console.log(newUser);
resolve(newUser);
}
});
}); // .then(getUserList);

Related

How do I get this function to run synchronously?

async await is very confusing. I have the below code and here I am trying to implement a create user function that first needs to check if the user exists in my MySQL database. I have the initial setting of the user where I call await on my findByUsername function. However, The function finishes after my if(!user) code has been executed.
I want the program to wait for the findByUsername function to finish and then perform the check on whether the user exists or not.
const { username, password, firstname, permission } = req.body;
let user = await User.findByName(req.body.username, (err, data) => {
if (err) {
if (err.kind === "not_found") {
console.log("finished");
return null;
} else {
console.error("error occurred");
}
} else {
console.log("finished too");
return data;
}
});
if (!user) {
console.log("couldnt find user");
res.status(404).send("couldnt find it :(");
} else {
console.log("found user");
res.send("found them");
}
===EDIT===
I am getting another that has also been confusing me where it says that result is not a function inside of my findByName function on my User model.
sql.query(`SELECT * from users WHERE username = '${username}'`, (err, res) => {
if (err) {
console.log("error ", err);
result(err, null);
return;
}
if (res.length) {
console.log("found user: ", res[0]);
result(null, res[0]);
return;
}
console.log("couldnt find");
return { kind: "not_found" }, null;
});
};
We must use await inside an async function.
For example:
const getUser = async (username) => await User.findByName(username);
Then call that function inside a try catch
try {
user = getUser(someUsername)
} catch (error) {
// Handle errors here
}
// Code here will only run once getUser is finished
Since i don't know your UserService i don't know if "User.FindByName" is a async function. but if that is the case you could do it like this:
const { username, password, firstname, permission } = req.body;
try {
let user = await User.findByName(req.body.username);
if (!user) {
console.log("couldnt find user");
res.status(404).send("couldnt find it :(");
} else {
console.log("found user");
res.send("found them");
}
} catch (e) {
res.status(400).send(e);
}
Are you able to change the definition of User.findByName?
Instead of using await and also passing in a callback, why not remove the callback and process it synchronously?
let user = await User.findByName(username);
// Handle response here
this will solve your Problem If you are using sequelize with mysql you can use where
condition in your code so you can use more conditions in it
const { username, password, firstname, permission } = req.body;
try {
let user = await User.findOne({
where: { username: req.body.username },
attributes: { exclude: ['password', 'signup_token'] }
});
if (!user) {
console.log("couldnt find user");
res.status(401).send("couldnt find user with username" +
(req.body.username));
} else {
console.log("User Found");
return res.status(200).send("User Found With Username" +
(req.body.username));
}
} catch (error){
console.log(error);
return res.status(500).send(error);
}
The function finishes after my if(!user) code has been executed.
That is because you are mixing async/await with callbacks which you should not.
// Here you are mixing async/await and callbacks
let user = await User.findByName(req.body.username, (err, data) => { /*....*/ });
// it is the same as
function findByNameCallback(err, data) { /*.....*/ }
let user = await User.findByName(req.body.username, findByNameCallback);
// -- So you either remove the callback from the equation
var user;
try {
user = await User.findByName(req.body.username);
} catch (err) {
// Handle error
}
// Work with the user object...
// ----
// Or remove the async/await stuff
User.findByName(req.body.username, findByNameCallback);

How to break out of a promise (.then) statement javascript

I'm having a problem trying to break out of a promise statement when an error occurs in a catch statement.
I'm not sure if I can throw an error inside a catch statement.
The problem: The catch function isn't doing anything when I throw an error.
Expected result: For the catch statement to display an alert and break the promise chain.
The code:
if (IsEmail(email)) {
$('body').loadingModal({
position: 'auto',
text: 'Signing you in, please wait...',
color: '#fff',
opacity: '0.9',
backgroundColor: 'rgb(0,0,0)',
animation: 'doubleBounce'
});
var delay = function(ms){ return new Promise(function(r) { setTimeout(r, ms) }) };
var time = 2000;
delay(time)
.then(function() { $('body').loadingModal('animation', 'foldingCube'); return delay(time); } )
.then(function() {
firebase.auth().signInWithEmailAndPassword(email, password)
.then(function () {
var user = firebase.auth().currentUser;
uid = user.uid;
configure();
})
.catch(function(error) {
throw error;
});
})
.then(function() { $('body').loadingModal('color', 'white').loadingModal('text', 'Welcome to Dtt deliveries').loadingModal('backgroundColor', 'orange'); return delay(time); } )
.then(function() { $('body').loadingModal('hide'); return delay(time); } )
.then(function() { $('body').loadingModal('destroy') ;} )
.catch(function(error) {
alert("Database error: " + error);
});
}
else {
alert("Please enter a valid email");
return;
}
The second .then after the delay resolves immediately, because nothing is being returned from it. Return the signInWithEmailAndPassword call instead, because it returns a Promise that you need to chain together with the outer Promise chain:
.then(function() {
return firebase.auth().signInWithEmailAndPassword(email, password)
// ...
Also, catching and immediately throwing doesn't really do anything - unless you need to handle an error particular to signInWithEmailAndPassword there, feel free to omit that catch entirely:
delay(time)
.then(function() { $('body').loadingModal('animation', 'foldingCube'); return delay(time); } )
.then(function() {
return firebase.auth().signInWithEmailAndPassword(email, password)
})
.then(function () {
var user = firebase.auth().currentUser;
uid = user.uid;
configure(); // if configure returns a Promise, return this call from the `.then`
})
.then(
// ...
.catch(function(error) {
alert("Database error: " + error);
});
If configure returns a Promise as well, then you need to return it too. (if it's synchronous, there's no need)
(you might also consider using a more user-friendly way of displaying the error, perhaps use a proper modal instead of alert)
Another option to consider is using await instead of all these .thens, the control flow may be clearer:
(async () => {
if (!IsEmail(email)) {
alert("Please enter a valid email");
return;
}
$('body').loadingModal({
position: 'auto',
text: 'Signing you in, please wait...',
color: '#fff',
opacity: '0.9',
backgroundColor: 'rgb(0,0,0)',
animation: 'doubleBounce'
});
var delay = function(ms) {
return new Promise(function(r) {
setTimeout(r, ms)
})
};
var time = 2000;
try {
await delay(time);
$('body').loadingModal('animation', 'foldingCube');
await delay(time);
await firebase.auth().signInWithEmailAndPassword(email, password)
var user = firebase.auth().currentUser;
uid = user.uid;
configure(); // if this returns a Promise, `await` it
$('body').loadingModal('color', 'white').loadingModal('text', 'Welcome to Dtt deliveries').loadingModal('backgroundColor', 'orange');
await delay(time);
$('body').loadingModal('hide');
await delay(time);
$('body').loadingModal('destroy');
} catch(error) {
alert("Database error: " + error);
}
})();

How to return a list of SQS queues in a module exports function?

I'm very new to node.js so I think I'm missing something obvious here.
I'm simply trying to get a list of SQS queues using aws-sdk and return them from a module to be accessible to other code. list_queues is the function in question.
The code below works to an extent, I see a "success" log and a log of a string array of all my queues, however, the function does not return that array to the caller and I don't understand why.
const AWS = require('aws-sdk');
AWS.config.update({region: 'eu-west-1'});
var sqs;
var sts = new AWS.STS();
sts.assumeRole({
RoleArn: 'arn:aws:iam::xxxxx:role/UserRole',
RoleSessionName: 'NodeDeveloperRoleSession'
}, function(err, data) {
if (err) { // an error occurred
console.log('Cannot assume role :(');
console.log(err, err.stack);
} else { // successful response
console.log('Assumed role success :)');
AWS.config.update({
accessKeyId: data.Credentials.AccessKeyId,
secretAccessKey: data.Credentials.SecretAccessKey,
sessionToken: data.Credentials.SessionToken
});
sqs = new AWS.SQS({apiVersion: '2012-11-05'});
}
});
exports.list_queues = function() {
sqs.listQueues({}, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("success");
console.log(data.QueueUrls);
return data.QueueUrls;
}
});
}
Any help is appreciated
exports.list_queues = function() { // 2. but you actually want to return from this one
sqs.listQueues({}, function(err, data) { <-----------------
if (err) { |
console.log("Error", err); |
} else { |
console.log("success"); |
console.log(data.QueueUrls); |
return data.QueueUrls; // 1. you are returning from this one
}
});
}
there are two ways you can make it work
Promise based
exports.list_queues = function() {
return sqs.listQueues({}).promise().then((data) => data.QueueUrls);
}
// and in another file you would:
const {list_queues} = require('./list_queues.js');
list_queues.then((queues) => console.log(queues));
Callback based
exports.list_queues = function(cb) { // notice I added callback here
sqs.listQueues({}, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("success");
console.log(data.QueueUrls);
cb(data.QueueUrls);
}
});
}
// and in another file you would:
const {list_queues} = require('./list_queues.js');
list_queues(function(queues) {
console.log(queues);
});
I strongly recommend you to use promise based approach, since it's much more readable and you can make use of async/await on it, which is great.

How to chain mongoose query using promises?

Hey guys I'm beginner and I'm working on my first express and mongo application but I don't know how to chain queries with javascript promises to make it work as a sync query.
Please help me to chain these mongoose queries.
/* POST Register User */
router.post('/register',function(req,res,next){
let user = req.body;
//checking for empty field in a form
for(let key in user){
if(user[key] === ""){
return next(mid.error("All fields are required to fill"));
}
}
User.findOne({username:user.username})
.exec(function(err,user){
if(err){
return next(mid.error("Something went wrong"));
}
if(user){
return next(mid.error("Username already exist"));
}
});
User.findOne({email:user.email})
.exec(function(err,user){
if(err){
return next(mid.error("Something went wrong"));
}
if(user){
return next(mid.error("Email already exist"));
}
});
//matching password
if(user.password !== user.confirm){
return next(mid.error("Password not matched.Try again !"));
}
//save data in object
let userData = {
username : user.username,
email : user.email,
password : user.password
};
//save data in database
User.create(userData,function(err,user){
if(err){
return next(mid.error("Something went wrong.Try again !!!"));
} else {
req.session.userID = user._id;
return res.redirect('/home');
}
});
});
/* POST Register User */
router.post('/register',function(req,res,next){
let user = req.body;
let validError = [];
//checking for empty field in a form
for(let key in user){
if(user[key] === ""){
return next(mid.error("All fields are required to fill"));
}
}
let findUserName = () => {
return new Promise(function(resolve,reject){
User.findOne({username:user.username})
.exec(function(err,user){
if(err){
validError.push("Something went wrong");
}
if(user){
validError.push("Username already exist");
}
return resolve();
});
});
}
let findUserEmail = () => {
return new Promise(function(resolve,reject){
User.findOne({email:user.email})
.exec(function(err,user){
if(err){
validError.push("Something went wrong");
}
if(user){
validError.push("Email already exist");
}
return resolve();
});
});
}
let isPasswordMatch = () => {
return new Promise(function(resolve,reject){
if(user.password !== user.confirm){
validError.push("Password not matched");
}
return resolve();
});
}
findUserName().then(findUserEmail).then(isPasswordMatch).then(() => {
if(validError.length == 0){
//save data in object
let userData = {
username : user.username,
email : user.email,
password : user.password
};
//save data in database
User.create(userData,function(err,user){
if(err){
return next(mid.error("Something went wrong.Try again !!!"));
} else {
req.session.userID = user._id;
return res.redirect('/home');
}
});
}else{
return next(mid.error(validError[0]));
}
});
});
Finally did my own ! Thanks all of you
Promise chaining is't always favourable, you have to analyse whether chaining is going to support your situation or will worsen your problem. In your case if any of the query { findByName, findByEmail, Create} fails you have to return back from there. If you try it with promise chaining then if any of the above operations fails even then the next .then or .catch of chained promises will get executed successively. So in my point of view all you need is Promise.all. Below I have provided the link of the code on jsfiddle. For your understanding I have given chaining approach but that is not recommended. Just go with Promise.all
with Promise.all
with promises chaining
Use Rx, and mongoose-observables :)
var Rx = require('rx');
var observables = require('mongoose-observables');
/* get public header data, list of collections and projects */
router.get("/header", function(req, res) {
let articleTitle = observables.finder.find(Articles, '{}', ['title'], null);
let collectionTitle = observables.finder.find(Collections, '{}', ['title'], null);
Rx.Observable.forkJoin([articleTitle, collectionTitle])
.subscribe(
(docs) => res.json(docs),
(err) => console.error(err)
);
});
More example at https://www.npmjs.com/package/mongoose-observables

Difference between new Promise and Promise.resolve/reject in bluebird

I call storage.createTask and use BlueBird's promises to get the returned value. This works fine when I do new Promise() and resolve the promise using either resolve(something) or reject(error). However, Promise.reject(new Error('some error')) causes cannot read property 'then' of undefined.
According to the docs, Promise.reject
Creates a promise that is rejected with the given reason
. Isn't this similar to reject(error), which works fine?
What's the difference between Promise.resolve/Promise.reject and doing new Promise? When should we use one over the other?
//server.js
// returning Promise.reject causes
// Cannot read property 'then' of undefined
storage.createTask(task).then(function(id) {
task.id = id;
reply(task);
}, function(error) {
console.log(error);
reply(error);
});
// storage.js
function _create(task) {
return new Promise(function(resolve, reject) {
var id = shortid.generate();
Task.create({
id: id,
content: task.content,
deadline: task.deadline,
milestone_id: task.milestone_id,
}).catch(function (error) {
reject(error); // works ok
}).then(function() {
resolve(id); //works ok
});
});
}
module.exports = {
createTask: function(task) {
if (task.milestone_id != null ) {
Milestone.isExist(task.milestone_id).then(function(exists) {
if (!exists) {
return Promise.reject(new Error('some error'));
}
return _create(task);
});
} else {
return _create(task);
}
}
Your createTask() function does not return anything; you need to return the promise created by Milestone.isExist().
Update
Here's how I would rewrite the function:
createTask: function(task) {
if (task.milestone_id == null ) {
return Promise.reject(new Error('null id'));
}
return Milestone.isExist(task.milestone_id).then(function(exists) {
if (!exists) {
return Promise.reject(new Error('some error'));
}
return _create(task);
});
}
With this rewrite, you are always returning a promise from createTask(), so you can safely chain off of it.

Categories

Resources