当向数据库发送2个查询显示passport配置中存在字段时,发送2条flash消息

sending 2 flash messages when 2 queries to the databse show that fields exist in passport configuration

本文关键字:字段 存在 发送 消息 flash 2条 配置 数据库 2个 passport 显示      更新时间:2023-09-26

注册时,我会检查数据库,看看用户名和电子邮件是否存在。如果存在,应该会返回错误。所有用户名和电子邮件都应该是唯一的。我的问题似乎是我只能犯一个错误。如果电子邮件已经存在,我会收到快闪消息,但如果用户名也存在,它不会说明用户名已经存在。我想显示这两个错误如果两者都已经存在于张贴在一个闪光消息

我认为问题是返回电子邮件的done()。由于我有两个查询,它只查看第一个被命中的查询。我真的不知道。

我试图对此进行研究,我知道你可以为req.flash传递一个数组,但我可以让它发挥作用,因为它会返回它看到的第一个存在的数组。

我还读到done的第三个参数是一个信息对象,我认为它提供了关于用户的信息,我曾考虑加载那里的现有信息,但我无法将其组合在一起。我也试过其他东西。但我只向您展示查询数据库的方法,因为我在中失败得很厉害

passport.use("local-signup", new LocalStrategy({
    usernameField : "email",
    passwordField : "password",
    passReqToCallback : true
},
    function(req, email, password, done){
        var arr = [];
        User.findOne({"email" : email}, function(err, user){
            if(err) return done(err);
            if(user){
                // arr.push("That email is already taken")
                return done(null, false, req.flash("signupMessage", "That username is taken"))
            }else{
                User.findOne({"username" : req.body.username}, function(err,user){
                    if(err) return done(err);
                    if(user){
                        // arr.push()
                        return done(null, false, req.flash("signupMessage", "That username is taken"))
                    }else{
                        var newUser = new User();
                        newUser.username = req.body.username;
                        newUser.password = password;
                        newUser.email = req.body.email;
                        newUser.save(function(err, doc){
                            if(err) throw err;
                            console.log("doc", " " , doc)
                            return done(null, newUser);
                        })                          
                    }
                })
            }
        })
    }
))

EJS-

app.get("/signup", function(req, res){
    console.log(req.session)
    console.log(req.flash("signupMessage"))
    res.render("signup", {authed : authed, user : user, message: req.flash("signupMessage")})
})
app.post("/signup",passport.authenticate("local-signup", {
    successRedirect : "/",
    failureRedirect : "/signup",
    failureFlash : true
}))

这是一个基本的控制流问题。你回来了。不要。将不得不重复一些代码作为它的一个额外功能,或者使用一个标志并在之前命中数据库。也不确定你将如何显示这两条消息,将不得不单独解决。将它们合并为一个("用户名和电子邮件已注册。请输入不同的用户名和电子邮件id。")

User.findOne({"email" : email}, function(err, user){
        if(err) return done(err);
        if(user){
            // arr.push("That email is already taken")
        // do not know what all done does maybe a ligther versio that just sends the error
            done(null, false, req.flash("signupMessage", "That Email is taken"))
        User.findOne({"username" : req.body.username}, function(err,user){
                if(err) return done(err);
                if(user){
                    // arr.push()
                    return done(null, false, req.flash("signupMessage", "That username is taken"))
                }//no else here
                         return;                         
        }else{
            User.findOne({"username" : req.body.username}, function(err,user){
                if(err) return done(err);
                if(user){
                    // arr.push()
                    return done(null, false, req.flash("signupMessage", "That username is taken"))
                }else{
                    var newUser = new User();
                    newUser.username = req.body.username;
                    newUser.password = password;
                    newUser.email = req.body.email;
                    newUser.save(function(err, doc){
                        if(err) throw err;
                        console.log("doc", " " , doc)
                        return done(null, newUser);
                    })                          
                }
            })
        }
    })
    }
))

调整控制流是解决此问题的一种方法,但如果您正在寻找更优雅的解决方案,则可以尝试promise.all()方法。

promise.all()所做的是,它实际上一次触发所有异步调用,并在何时返回;

  1. 所有异步调用都成功(解析)
  2. 异步调用中的任意1返回reject(失败)

显然,第2点并不是您想要的,因为您想要同时报告电子邮件和用户名,以应对它们不唯一的情况。

要解决此问题,您必须使用reflect使promise.all()仅在所有承诺都已回复(成功或失败)时返回。

考虑以下代码:

this.reflect = function reflect(promise){
  return promise.then(function(/*resolve return value=*/v){ return { v:v, status: "resolved" }},
      function(/*rejection error=*/e){ return { e:e, status: "rejected" }});
};
var promises = [
  new Promise(function(resolve, reject) {
    // User.findOne({"username" : req.body.username}, function(err,user){
    // if (err) { return reject("error!"); }...
    // resolve("Name is unique!!");
    // });
    resolve("name is unique");
  }),
  new Promise(function(resolve, reject) {
    reject("email is NOT unique");
  })
];
Promise.all(promises.map(this.reflect)).then(function(results) {
  if (results[0].status === "rejected") {
    console.log("Error reason: " + results[0].e);
  }
  else {
    console.log("Succeeds, reason: " + results[0].v);
  }
  if (results[1].status === "rejected") {
    console.log("Error reason: " + results[1].e);
  }
  else {
    console.log("Succeeds, reason: " + results[1].v);
  }
  // You can call whatever callback you want here.
  // e.g. return done(null, "Test");
});

输出:

成功,原因:名称唯一
错误原因:电子邮件不是唯一的

注意:您应该能够对上面的代码进行一些修改,以满足您的需求。如果你还有麻烦,就大声叫我。

参考:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise

试试看:

    var signupMessages = [];
    User.findOne({"email" : email}, function(err, user){
        if(err) return done(err);
        if(user) signupMessages.push("That email is taken");
        User.findOne({"username" : req.body.username}, function(err,user){
                if(err) return done(err);
                if(user) signupMessages.push("That username is taken");
                if(signupMessages.length > 0){
                    return done(null, false, req.flash("signupMessage", signupMessages));
                } else { ...

在这种情况下,req.flash("signupMessage")将返回消息数组