Javascript 在同一请求中进行两个方法调用

Javascript 在同一请求中进行两个方法调用,javascript,node.js,mongodb,express,mongoose,Javascript,Node.js,Mongodb,Express,Mongoose,简要概述我正在努力实现的目标: 在前端,用户可以使用表单编辑有关其帐户的信息。然后,无论编辑/触摸了多少字段,该表单都会发送到相同的HTTP请求 我的想法是,请求将处理要编辑的字段。除了我不确定如何返回确认数据外,这个逻辑对我来说似乎是合理的。例如,它如何知道所有请求何时完成/显示哪些确认和错误消息 //Change information route router.post('/changeinformation', passport.authenticate('jwt', {session:

简要概述我正在努力实现的目标:

在前端,用户可以使用表单编辑有关其帐户的信息。然后,无论编辑/触摸了多少字段,该表单都会发送到相同的HTTP请求

我的想法是,请求将处理要编辑的字段。除了我不确定如何返回确认数据外,这个逻辑对我来说似乎是合理的。例如,它如何知道所有请求何时完成/显示哪些确认和错误消息

//Change information route
router.post('/changeinformation', passport.authenticate('jwt', {session: false}), (req, res, next) => {
    const changeInfo = {
        changeEmail: req.body.changeEmail,
        changeUsername: req.body.changeUsername
    };

    if(changeInfo.changeUsername === true) {
        const userInfo = {
            email: req.body.email,
            currentEmail: req.body.currentEmail
        };
        Artist.getArtistByEmail(userInfo.email, (err, user) => {
            if (err) throw err;
            if (user) {
                return res.json({success: false, msg: 'Email already exists'});
            }
            else {
                Artist.changeEmail(userInfo, (err, callback) => {
                    if (callback) {
                        console.log(callback);
                        return res.json({success: true, msg: 'Email has been changed successfully'});
                    }
                });
            }
        });
    }

    if(changeInfo.changeUsername === true) {
        //Checks if username exists
        const nameInfo = {
            name: req.body.name,
            currentName: req.body.currentName
        };
        Artist.getArtistByName(userInfo.name, (err, user) =>
        {
            if (err) throw err;
            if (user) {
                return res.json({success: false, msg: 'Name already exists'});
            }
            else
            {
                Artist.changeName(userInfo, (err, callback) => {
                    if(callback)
                    {
                        console.log(callback);
                        return res.json({success: true, msg: 'Name has been changed successfully'});
                    }
                });
            }
        });
    }
});

如果这对某些人来说是显而易见的,我很抱歉。我仍在学习,不确定如何处理这个问题。谢谢

第一个
if(changeInfo.changeUsername==true)
应该是
if(changeInfo.changeEmail==true)
遵循您的逻辑。

这里真的不需要打多个电话,或者几乎没有效率。您可以根据所选选项生成查询并更新,而不是进行多次调用

也完全没有必要为修改每个属性构造不同的方法。正确表达后,标准mongoose(实际上是MongoDB)方法应该足够描述预期的功能。否则做起来既麻烦又不切实际,而构建查询选项而不是特定的属性调用通常是指:

router.post('/changeinformation',
  passport.authenticate('jwt', {session: false}), (req, res) => {

  let query = { },
      update = { $set: { } };

  if ( req.body.changeEmail ) {
    query['email'] = req.body.currentEmail;   // presuming this is current
    update.$set['email'] = req.body.email;
  }

  if ( req.body.changeUsername ) {
    query['name'] = req.body.currentName;
    update.$set['name'] = req.body.name;
  }

  // One call only
  User.update(query,update,(err,result) => {
    if (err) {
      if (err.code === 11000) {     // Duplicate key error
        res.json({ success: false, msg: 'email or name already exists' });
      } else {
        res.json({ success: false, msg: err.message });
      }
    } else {
      if ( result.n === 0 ) {
        res.json({ success: false, msg: 'Requested details not found' });
      } else {
        res.json({ success: true, msg: 'Details updated successfully' });
      }
    }

  });

});
因此,您只需检查提供的选项并从中构建查询和更新语句,而不是进行分支和进行不同的调用。这些是“按设计”的常规对象表示,与任何对象一样,您只需操纵结构来构造它们

这里的第一个主要出发点是使用查询来“检查目标值的存在”,以进行更改。那真是效率低下。您真正需要的是,这些值应该是“唯一的”,这样集合中的其他对象就不能共享相同的
名称
电子邮件
。强制执行此操作的方式是使用“索引”:

模式中的
“unique”
属性告诉mongoose在该属性上创建一个“unique”索引。如果您尝试在集合中添加多个相同的值(即将用户名更改为与现有条目相同的值),则这将引发“重复键错误”,我们可以通过错误代码捕获该错误并相应地作出响应

这就是代码所做的,通过测试返回的错误代码,并在识别为重复密钥错误时给出相应的消息作为响应:

      if (err.code === 11000) {
        res.json({ success: false, msg: 'email or name already exists' });
      } else {
        res.json({ success: false, msg: err.message });
      }
这比单独查询测试目标值是否已经存在要直接得多。此外,它更可靠,因为在当前代码中的“查询”和后续“更新”之间,可能会有其他内容实际更改数据。因此,如果不强制执行唯一索引并检查错误,您就有创建重复项的风险。因此,为正确的工作使用正确的工具

这里的另一个检查当然是查看更新是否匹配任何内容。这总是包含在
n
属性下的响应对象中,该属性表示实际匹配条件的文档数

至于消息本身,您可以让它们保持“原样”,我个人认为这是完全合理的,或者您也可以在请求参数上使用与语句构造类似的分支逻辑来确定要返回的特定消息内容

例如:

let errStr = (req.body.changeEmail && req.body.changeUsername)
  ? "email or name" 
  : ( req.body.changeEmail ) ? "email" : "name";
res.json({ success: false, msg: `${errStr} already exists` });
希望你能大致了解情况

但这比尝试将不同的调用链接在一起并在您确实不需要时发出多个请求要好得多


作为旁注,我们实际上有比使用回调嵌套更现代、更推荐的处理方法。承诺已经存在了一段时间,您也确实应该在一个支持/syntax的环境中工作,就像任何nodejs v8.x.x版本所做的那样,这实际上即将成为长期支持(LTS)版本:


当你真的有一系列异步函数需要解析时,它就变成了它自己的问题,而我们在这个例子中真正想要避免的就是这个问题。但一般情况下,即使包含块,也至少有一个更合理的流程,并确实提高了代码的可读性。

这正是我想要的。我知道我做这件事的方式有根本性的问题。非常感谢。
let errStr = (req.body.changeEmail && req.body.changeUsername)
  ? "email or name" 
  : ( req.body.changeEmail ) ? "email" : "name";
res.json({ success: false, msg: `${errStr} already exists` });
router.post('/changeinformation',
  passport.authenticate('jwt', {session: false}), async (req, res) => {

  let query = { },
      update = { $set: { } };

  if ( req.body.changeEmail ) {
    query['email'] = req.body.currentEmail;   // presuming this is current
    update.$set['email'] = req.body.email;
  }

  if ( req.body.changeUsername ) {
    query['name'] = req.body.currentName;
    update.$set['name'] = req.body.name;
  }

  try {
    let result = await User.update(query,update);

    if ( result.n === 0 ) {
      let msgStr = (req.body.changeEmail && req.body.changeUsername)
        ? "email or name"
        : ( req.body.changeEmail ) ? "email" : "name";
      res.json({ success: false, msg: `Requested ${msgStr} not found` });
    } else {
      res.json({ success: true, msg: 'Details updated successfully' });
    }

  } catch(e) {
    if (e.code === 11000) {
      let errStr = (req.body.changeEmail && req.body.changeUsername)
        ? "email or name"
        : ( req.body.changeEmail ) ? "email" : "name";
      res.json({ success: false, msg: `${errStr} already exists` });
    } else {
      res.json({ success: false, msg: e.message });
    }
  }
});