node.js - avoid multiple returns looped in javascript - async / await to solve callback pyramid or callback hell, -


i have code, lot of blocks of returns, example signup()

connectors.js

  const connectors = {       auth: {         signup(args) {           return new promise((resolve, reject) => {             // validate data             if (!args.email) {               return reject({                 code: 'email.empty',                 message: 'email empty.'               });             } else if (!isemail(args.email)) {               return reject({                 code: 'email.invalid',                 message: 'you have provide valid email.'               });             }              if (!args.password) {               return reject({                 code: 'password.empty',                 message: 'you have provide password.'               });             }              return encryptpassword(args.password, (err, hash) => {               if (err) {                 return reject(new error('the password not 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 user email.'                     });                   }                    return reject(err2);                 });             });           });         },     };      module.exports = connectors; 

then anoter code call 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 avoid in es6 or es7 or es2017?

there are:

  return()    .then()      return()        .then 

and loop returns:

return()    return()        return() 

comming php code looks crazy, because return functions return functions, , it's not clear me, how name in javascript type of block return code? calling functions returns again more code?

updated:

code not mine, full source in

https://github.com/jferrettiboke/react-auth-app-example

i'd understand example:

    return encryptpassword(args.password, (err, hash) => {       if (err) {         return reject(new error('the password not hashed.'));       }        return user.create(object.assign(args, { password: hash }))         .then((user) => {         .catch((err2) => {            return reject(err2); 

/src/utils/auth.js (here encryptpassword)

const jwt = require('jsonwebtoken'); const bcrypt = require('bcrypt-nodejs'); const config = require('../config'); exports.encryptpassword = (password, callback) => {   // generate salt run callback   bcrypt.gensalt(10, (err, salt) => {     if (err) { return callback(err); }      // hash (encrypt) our password using salt     return bcrypt.hash(password, salt, null, (err2, hash) => {       if (err2) { return callback(err2); }       return callback(null, hash);     });   }); }; 

there 3 returns calling functions , returning values , functions? oop never this, how use async/await suggest @dashmud, don't want learn old things callbacks

this code needs refactored in number of ways. first, really, don't want mix promises , plain async callbacks in same logic flow. makes mess , wrecks lot of advantages of promises. then, have anti-pattern going using promises inside of new promise(). then, have more nesting required (you can chain instead).

here's i'd suggest:

function encryptpasswordpromise(pwd) {     return new promise((resolve, reject) => {         encryptpassword(pwd, (err, hash) => {             err ? reject(new error("the password not hashed.")) : resolve(hash);         });     }); }  const connectors = {     auth: {         signup(args) {             // validate data             let err;             if (!args.email) {                 err = {code: 'email.empty', message: 'email empty.'};             } else if (!isemail(args.email)) {                 err = {code: 'email.invalid', message: 'you have provide valid email.'};             } else if (!args.password) {                 err = {code: 'password.empty', message: 'you have provide password.'};             }             if (err) {                 return promise.reject(err);             } else {                 return encryptpasswordpromise(args.password).then(hash => {                     args.password = hash;                     return user.create(args);                 }).then((user) => {                     return createtoken({id: user._id, email: user.email});                 }).catch(err2 => {                     if (err2.code === 11000) {                         throw new error({code: 'user.exists', message: 'there user email.'});                     } else {                         throw err2;                     }                 });             }         }     } }; 

summary of changes:

  1. collect errors , return promise.reject(err) in 1 place initial errors.
  2. promisify encryptpassword() aren't mixing regular callbacks promise logic flow , can return , propagate errors.
  3. removing wrapping of whole code return new promise() since async operations promisified can return promises directly. helps proper error handling too.
  4. undo unneccessary nesting , chain instead.
  5. remove object.assign() there did not appear reason it.

in edit, asked explanation of code segment:

return encryptpassword(args.password, (err, hash) => {   if (err) {     return reject(new error('the password not hashed.'));   }    return user.create(object.assign(args, { password: hash }))     .then((user) => {     .catch((err2) => {        return reject(err2); 
  1. this code calls encryptpassword().
  2. it returns result of undefined return doing controlling program flow (exiting containing function), since there no code after return @ same level, that's unnecessary.
  3. you pass callback encryptpassword(). callback asynchronous, meaning called time later.
  4. the callback gets 2 arguments: err , hash. in node.js async calling convention, if first argument truthy (e.g. contains truthy value), represents error. if falsey (usually null), there no error , second argument contains result of asynchronous operation.
  5. if there error, parent promise rejected , callback exited. again, there no return value reject return exiting callback @ point (so no other code in callback runs).
  6. then, asynchronous operation user.create() called , passed args object new password set in it.
  7. user.create() returns promise result captured .then() method , callback passed that.
  8. some time later, when asynchronous user.create() finishes, resolve promise , cause .then() callback called , result passed it. if there's error in operation, .then() callback not called, instead .catch() callback called. in .catch() callback, parent promise rejected. promise anti-pattern (resolving parent promise inside promise) because easy make mistakes in proper error handling. answer shows how avoid that.

Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -