I have this code, with a lot of blocks of returns, by example SignUp()
connectors.js
const connectors = {
Auth: {
signUp(args) {
return new Promise((resolve, reject) => {
// Validate the data
if (!args.email) {
return reject({
code: 'email.empty',
message: 'Email is empty.'
});
} else if (!isEmail(args.email)) {
return reject({
code: 'email.invalid',
message: 'You have to provide a valid email.'
});
}
if (!args.password) {
return reject({
code: 'password.empty',
message: 'You have to provide a password.'
});
}
return encryptPassword(args.password, (err, hash) => {
if (err) {
return reject(new Error('The password could not be hashed.'));
}
return User.create(Object.assign(args, { password: hash }))
.then((user) => {
resolve(createToken({ id: user._id, email: user.email }));
})
.catch((err2) => {
if (err2.code === 11000) {
return reject({
code: 'user.exists',
message: 'There is already a user with this email.'
});
}
return reject(err2);
});
});
});
},
};
module.exports = connectors;
then anoter code that call this code:
const connectors = require('./connectors');
CallsignUp(root, args) {
const errors = [];
return connectors.Auth.signUp(args)
.then(token => ({
token,
errors
}))
.catch((err) => {
if (err.code && err.message) {
errors.push({
key: err.code,
value: err.message
});
return { token: null, errors };
}
throw new Error(err);
});
}
how it's possible to avoid this in ES6 or ES7 or ES2017?
there are:
return()
.then()
return()
.then
and just loop returns:
return()
return()
return()
comming from PHP this code looks crazy, because return functions that return functions, and it's not clear for me, how is the name in javascript this type of block return code? calling functions that returns again more code?
UPDATED:
Code is not mine, full source in
https://github.com/jferrettiboke/react-auth-app-example
I'd like to understand by example:
return encryptPassword(args.password, (err, hash) => {
if (err) {
return reject(new Error('The password could not be hashed.'));
}
return User.create(Object.assign(args, { password: hash }))
.then((user) => {
.catch((err2) => {
return reject(err2);
/src/utils/auth.js (here is encryptPassword)
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt-nodejs');
const config = require('../config');
exports.encryptPassword = (password, callback) => {
// Generate a salt then run callback
bcrypt.genSalt(10, (err, salt) => {
if (err) { return callback(err); }
// Hash (encrypt) our password using the salt
return bcrypt.hash(password, salt, null, (err2, hash) => {
if (err2) { return callback(err2); }
return callback(null, hash);
});
});
};
there are 3 returns calling functions and returning values and functions? OOP is never like this, how to use Async/Await suggest by @dashmud, i don't want to learn old things like callbacks
Extending @jfriend00's answer, here's an approach that uses the ES2017
async
/await
syntax to flatten the callback pyramid or callback hell, however you prefer to call it:Rather than handwrite my own promisified promise-based
encryptPassword()
, I opted to use a node.js builtin transformation function for that calledutil.promisify()
.Overall, there are still a few improvements that could be made like moving the validation of the
signUp()
arguments to a separate function, but none of that is related to flattening the "callback hell" anti-pattern that gave rise to promise-based control-flow and async/await syntax.