JavaScript节点-如何重构这一点

JavaScript节点-如何重构这一点,javascript,node.js,mongodb,express,Javascript,Node.js,Mongodb,Express,所以我正在创建一个简单的CRUD应用程序,但我在获取最新创建的帐户的MongoDB自动递增值时遇到了麻烦 更具体地说,我写了下面的花絮来实现以下功能: 1) 注册时,进行一些验证检查 2) 检查最近的帐号是多少,递增1 3) 创建新用户,添加到数据库 现在,如果你看到下面,我已经标记了三个展品 1&2)出于某种奇怪的原因,如果我从路由本身删除代码,那么它将停止正常工作,但我不知道如何摆脱重复代码,因为函数几乎完全相同,但删除其中任何一个都会破坏序列。我怎样才能解决这个问题,使我的代码更整洁 3)

所以我正在创建一个简单的CRUD应用程序,但我在获取最新创建的帐户的MongoDB自动递增值时遇到了麻烦

更具体地说,我写了下面的花絮来实现以下功能:

1) 注册时,进行一些验证检查

2) 检查最近的帐号是多少,递增1

3) 创建新用户,添加到数据库

现在,如果你看到下面,我已经标记了三个展品

1&2)出于某种奇怪的原因,如果我从路由本身删除代码,那么它将停止正常工作,但我不知道如何摆脱重复代码,因为函数几乎完全相同,但删除其中任何一个都会破坏序列。我怎样才能解决这个问题,使我的代码更整洁

3) 如何将此函数提取到单独的函数中?在摆弄了这个之后,我只到了“accountNumber未定义”的地步


非常感谢您的反馈

您可以这样做:

const getLastAccountNumber = function() {
  return User.find({}, { accountNumber: 1, _id: 0 })
    .sort({ accountNumber: -1 })
    .limit(1)
    .then(function(doc) {
      if (!doc) throw new Error("Error?");
      return doc[0].accountNumber;
    });
};

router.post(
  "/register",
  [check("email").isEmail(), check("password").isLength({ min: 4 })],
  function(req, res) {
    getLastAccountNumber().then((accountNumber) => {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(422).json({ errors: errors.array() });
      }
      const { email, password } = req.body;
      const amount = 0;
      accountNumber++;
      const user = new User({
        email,
        password,
        accountNumber,
        amount
      });
      user.save(function(err) {
        if (err) {
          console.log(err);
          res.status(500).send("Error registering new user");
        } else {
          res.status(200).send("User successfully added");
        }
      });
    });
  }
);

关于您的错误,我相信通过添加
let accountNumber到文件顶部可能足以让代码正常工作(尽管我不认为这是一个很好的解决方案…),但正如您所问的重构:

  • 拥抱承诺:想象水/数据流过一系列管道,在每一步中,数据都可以被转换。保持这种线性流通常会使代码干净且易于遵循。如果途中发生任何错误,将绕过“catch”之前的所有管道
  • 如果发生错误,我们直接开始“捕获”,我们可能希望根据失败原因以不同的方式处理这种情况。因此,我们可以添加诸如
    ValidationError
    之类的错误包装来检查错误
  • 此外,我们可以正确地命名管道,比如
    getNewAccountNumber
    ,即使数据库中没有帐户,它也可以工作
  • 箭头函数很好


无论如何,如果可能的话,我更愿意将其作为一个事务处理,使用现有的db内置解决方案(例如,“保证”id是唯一的,使用此解决方案的accountNumber没有那么多)。

什么是
accountNumber=doc[0]。accountNumber应该怎么做?还有<代码>accountNumber++;accountNumber从未定义过!尝试添加
let accountNumber到页面顶部code@LeonardPauli该赋值采用数据库中最新的现有accountNumber的值,以便accountNumber++执行一个加号(例如,我最近注册的帐户的帐号为4900,其想法是从数据库中注册值,将值增加1,并使用新帐号创建一个新用户,新帐号为4901 P.S。添加“let accountNumber”无效。返回“TypeError:无法读取未定义的属性';然后';”……等一下,它成功了!@Altair312您是否已将
return
语句添加到
getLastAccountNumber
函数中?哦,现在我看到了不同之处,我尝试手动修改代码,但不起作用;决定直接复制粘贴,现在起作用了。因此,当您执行类似操作时,请放置一个“return”在承诺旁边,那么“.then”条款起作用了吗?或者它是如何起作用的work@Altair312现在,
getLastAccountNumber
函数返回一个
Promise
,这就是为什么您可以对返回值
getLastAccountNumber()调用
then
。然后(…)
再往前走,我想模拟从一个帐户到另一个帐户发送交易(比如,从帐户10001到10009发送40虚拟美元),我如何将其转换为一个人类可理解的id选择?至于您的代码建议,我发现非常简洁,将尝试创建类似的东西(很高兴您喜欢它:)通常,id应该保持“隐藏”。此外,你希望你的用户能够“猜测”帐户id,或者看看你有多少个帐户id?我可能会生成一个“显示名”,它是人类可读的(例如,4个随机无意义的单词),并且可以在以后更改(但不适用于以前使用过的任何人).这样,人们就可以很容易地识别出他们最常用的帐户,而身份证将被隐藏起来使用。
const getLastAccountNumber = function() {
  return User.find({}, { accountNumber: 1, _id: 0 })
    .sort({ accountNumber: -1 })
    .limit(1)
    .then(function(doc) {
      if (!doc) throw new Error("Error?");
      return doc[0].accountNumber;
    });
};

router.post(
  "/register",
  [check("email").isEmail(), check("password").isLength({ min: 4 })],
  function(req, res) {
    getLastAccountNumber().then((accountNumber) => {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(422).json({ errors: errors.array() });
      }
      const { email, password } = req.body;
      const amount = 0;
      accountNumber++;
      const user = new User({
        email,
        password,
        accountNumber,
        amount
      });
      user.save(function(err) {
        if (err) {
          console.log(err);
          res.status(500).send("Error registering new user");
        } else {
          res.status(200).send("User successfully added");
        }
      });
    });
  }
);
// error handling

class ValidationError {
  constructor (errors) {
    this.errors = errors
  }
}

const checkValidation = (req, res)=> {
  const errors = validationResult(req)
  return errors.isEmpty()
    ? Promise.resolve()
    : Promise.reject(ValidationError(errors.array()))
}

const successResponse = (req, res, data)=> ()=> res.status(200).send(data)
const errorResponse = (req, res, message = 'Internal Server Error')=> error=>
    error instanceof ValidationError ? res.status(422).json({ errors: error.errors })
  : (console.error(error), res.status(500).send(message))


// utils

const initialAccountNumber = 0
const getNewAccountNumber = ()=> User
  .find({}, { accountNumber: true, _id: false })
  .sort({ accountNumber: -1 })
  .limit(1)
  .then(xs=> !xs || !xs.length
    ? initialAccountNumber
    : xs[0].accountNumber + 1)


// route

router.post('/register', [
  check('email').isEmail(),
  check('password').isLength({ min: 4 })
], (req, res)=> checkValidation(req, res)
  .then(getNewAccountNumber)
  .then(newAccountNumber=> {
    const { email, password } = req.body
    return new User({
      email,
      password,
      accountNumber: newAccountNumber,
      amount: 0,
    })
  })
  .then(user=> user.save())
  .then(successResponse(req, res, 'User successfully added'))
  .catch(errorResponse(req, res, 'Error registering new user'))
)