避免在javascript中循环多次返回-异步/等待解决回调金字塔或回调地狱, [英] avoid multiple returns looped in javascript - async / await to solve callback pyramid or callback hell,

查看:115
本文介绍了避免在javascript中循环多次返回-异步/等待解决回调金字塔或回调地狱,的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这段代码,包含很多返回块,例如SignUp()

I have this code, with a lot of blocks of returns, by example SignUp()

connectors.js

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);
        });
    } 

在ES6或ES7或ES2017中如何避免这种情况?

how it's possible to avoid this in ES6 or ES7 or ES2017?

有:

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

并循环循环返回:

return()
   return()
       return()

从PHP来的这段代码看起来很疯狂,因为返回函数会返回函数,而对于我来说还不清楚,javascript中这种类型的块返回代码的名称如何?调用返回更多代码的函数?

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?

已更新:

代码不是我的,提供了完整的源代码

Code is not mine, full source in

https://github.com/jferrettiboke/react-auth-app-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(这里是cryptoPassword)

/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);
    });
  });
};

有3个return调用函数以及返回值和函数吗? OOP从来都不是这样,@ dashmud建议如何使用Async/Await,我不想学习回调之类的老东西

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

推荐答案

扩展 @ jfriend00的答案,这是一种解决方法使用 ES2017 async/await 语法将回调金字塔

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:

const encryptPasswordPromise = require('util').promisify(encryptPassword)

const connectors = {
  Auth: {
    async signUp (args) {
      const { email, password } = args
      // Validate the data
      let err

      if (!email) {
        err = { code: 'email.empty', message: 'Email is empty.' }
      } else if (!isEmail(email)) {
        err = { code: 'email.invalid', message: 'You have to provide a valid email.' }
      } else if (!password) {
        err = { code: 'password.empty', message: 'You have to provide a password.' }
      }

      if (err) {
        throw err
      }

      let hash

      try {
        hash = await encryptPasswordPromise(password)
      } catch (err) {
        throw new Error('The password could not be hashed.')
      }

      const { _id: id, email } = await User.create(Object.assign(args, { password: hash }))

      try {
        return createToken({ id, email })
      } catch (err) {
        if (err.code === 11000) {
          throw { code: 'user.exists', message: 'There is already a user with this email.' }
        } else {
          throw err
        }
      }
    }
  }
}

module.exports = connectors

我没有手写我自己的基于承诺的基于承诺的encryptPassword(),而是选择使用node.js内置的转换函数来调用

Rather than handwrite my own promisified promise-based encryptPassword(), I opted to use a node.js builtin transformation function for that called util.promisify().

总体而言,仍可以进行一些改进,例如将signUp()参数的验证移至一个单独的函数,但是这些都与拉平"callback hell"反模式有关,后者导致了基于Promise的控制流和async/await语法.

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.

这篇关于避免在javascript中循环多次返回-异步/等待解决回调金字塔或回调地狱,的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆