Hey, je développe l'API d'une application en nodejs avec express et mongodb et je fais fasse à un pb que je sais pas résoudre proprement, je suis pas un pro du js :
je reçois un formulaire comprenant un pseudo, une adresse mail et un password.
le pseudo et l'adresse mail doivent faire fasse à une vérification de la base de donnée pour vérifier qu'ils sont pas déjà utilisés en plus d'une vérification via un regex. Le soucis étant que mon client est une appli react, au cas où la vérification foire, pour que mon client puisse afficher proprement les erreurs je renvoie un json avec toutes les erreurs possibles :
let response = {
"nickName": {
"valid" : null,
"available" : null // check de la BD
},
"mail" : {
"valid" : null,
"available" : null // check de la BD
},
"password" : {
"valid" : null
},
}voilà comment je fais mon check :
if(nickName && nickNameRegex.test(nickName)){
response["nickName"]["valid"] = true;
DB_access.checkUserNickname(nickName).then((e)=>{ // promise
if(e.length>0){
response["nickName"]["available"] = false;
}else{
response["nickName"]["available"] = true;
}
}).catch((e)=>{
console.log("Nickname checking ERROR : ",e);
});
}else{
response["nickName"]["valid"] = false;
}Ce bout de code là n'est que pour le nickname. Il y a juste après exactement la même chose appliquée à l'email puis une simple vérif regex pour le password mais comme vous vous en doutez, ça ne marche pas. Effectivement, la réponse (le json du début) m'indique que le serveur renvoie une valeur avant d'avoir fait le check sur la base de donnée.
Donc voilà ma question. Dois-je réellement imbriquer les promise ? Comment vous feriez pour renseigner les potentielles erreurs au client pour que l'user puisse savoir si son pseudo est pris/invalide etc.. ? (sachant qu'il y a déjà un test regex chez le client mais bon, on ne sait jamais
)
Voilà le code de la fonction entière si ça peut aider à la compréhension :
const postRegister = (req,res)=>{
/*
We receive data from client :
nickName : must be unique + valid (alphanumerical only)
mail : must be unique too
password : must be valid
server provided data :
creation date
active : boolean
*/
const nickNameRegex = new RegExp("^[a-zA-Z0-9]{3,15}$","g")
const passwordRegex = new RegExp("^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$","g");
const emailRegex = new RegExp("([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$","g");
const birthDateRegex = new RegExp("^\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])$","g");
const data = req.body;
const nickName = data["nickName"];
const mail = data["mail"];
const date = new Date().getTime();
const active = true;
const mailValid = false;
const birthDate = data["birthDate"];
const password = data["password"];
let response = {
"nickName": {
"valid" : null,
"available" : null
},
"mail" : {
"valid" : null,
"available" : null
},
"password" : {
"valid" : null
},
"birthDate" : {
"valid" : null
}
}
/*
response will be json to check if criterias (valid and avalaible) are ok
*/
// NICKNAME CHECKING
if(nickName && nickNameRegex.test(nickName)){
response["nickName"]["valid"] = true;
DB_access.checkUserNickname(nickName).then((e)=>{
if(e.length>0){
response["nickName"]["available"] = false;
}else{
response["nickName"]["available"] = true;
}
}).catch((e)=>{
console.log("Nickname checking ERROR : ",e);
});
}else{
response["nickName"]["valid"] = false;
}
// PASSWORD CHECKING
if(password && passwordRegex.test(password)){
response["password"]["valid"] = true;
}else{
response["password"]["valid"] = false;
}
// MAIL CHECKING
if(mail && emailRegex.test(mail)){
response["mail"]["valid"] = true;
DB_access.checkUserEmail(mail,(err,res)=>{
if(err){
console.log("EMAIL CHECKING SERVER ERROR : ",mail);
}else{
if(res.length>0){
response["mail"]["available"] = false;
}else{
response["mail"]["available"] = true;
}
}
});
}else{
response["mail"]["valid"] = false;
}
//Birthdate CHECKING
if(birthDate && birthDateRegex.test(birthDate)){
response["birthDate"]["valid"]=true;
}else{
response["birthDate"]["valid"]=false;
}
if(response["nickName"]["valid"] && response["nickName"]["available"]
&& response["mail"]["valid"] && response["mail"]["available"]
&& response["birthDate"]["valid"] && response["password"]["valid"]){
res.json(200).json(response);
}else{
res.status(403).json(response);
}
}
module.exports = {postRegister};Je cherche donc une méthode pour rendre ce code propre, c'est une vraie application qui vise à être déployée.
Je ne suis pas un pro non plus, mais déjà, pourquoi tu utilises les string + crochets pour spécifier des propriétés ?
genreconst mail = data["mail"];
au lieu deconst mail = data.mail ?
Ce serait plus joli à voir, les crochets ça a un intérêt surtout si tu veux les utiliser avec une variable, genreconst mail = data[maVar)
Pour tonif(e.length>0){
response["nickName"]["available"] = false;
}else{
response["nickName"]["available"] = true;
}
autant utiliser un opérateur ternaire :<code>e.length > 0 ? response["nickName"]["available"] = false :
/*********************/response["nickName"]["available"] = true
(le /****/ c'est juste pour l faire un espace parce qu'avec la mise en page de jvc...)
d'ailleurs je crois que tu peux même faire :response["nickName"]["available"] = e.length > 0 ? false : true;
voir même sans les crochets :response.nickName.available = e.length > 0 ? false : true;
Le 30 avril 2021 à 20:01:39 :
Je ne suis pas un pro non plus, mais déjà, pourquoi tu utilises les string + crochets pour spécifier des propriétés ?
genreconst mail = data["mail"];
au lieu deconst mail = data.mail?
Ce serait plus joli à voir, les crochets ça a un intérêt surtout si tu veux les utiliser avec une variable, genreconst mail = data[maVar)Pour ton
if(e.length>0){ response["nickName"]["available"] = false; }else{ response["nickName"]["available"] = true; }
autant utiliser un opérateur ternaire :<code>e.length > 0 ? response["nickName"]["available"] = false : /*********************/response["nickName"]["available"] = true
(le /****/ c'est juste pour l faire un espace parce qu'avec la mise en page de jvc...)d'ailleurs je crois que tu peux même faire :
response["nickName"]["available"] = e.length > 0 ? true : false;
voir même sans les crochets :response.nickName.available = e.length > 0 ? true : false;
Yes exact, c'est vrai que pour une bonne lisibilité il faudrait que je fasse ça.
Là où se porte le gros de ma question est vis à vis de la gestion des vérifications de ma base de données. vu que les vérifications ne renvoient que des promise, faut-il absolument que j'imbrique les promises ? genre
check1.then(()=>{check2.then(()=>{...})})
Ça malheureusement je pourrais pas t'aider, j'utilise pas énormément les promise et encore moins imbriquées ^^'
Pour ce qui est de la question des promises : les promises ça ne s'imbrique pas, ça se chaîne.
retrieveA()
.then(a => {
return retrieveB(a)
})
.then(b => {
// do something
})
.catch(err => {
// handle errors
})
Le 30 avril 2021 à 20:40:45 :
Pour ce qui est de la question des promises : les promises ça ne s'imbrique pas, ça se chaîne.retrieveA() .then(a => { return retrieveB(a) }) .then(b => { // do something }) .catch(err => { // handle errors })
Ah putain, ça c'est pas mal intéressant, je pensais pas qu'on pouvait faire ça ! Cimer chef
Du coup j'ai trouvé une forme propre pour faire marcher mon code avec les promises. Finalement j'ai pas chaîner les promise parce qu'en fait, vu que je consulte ma BD uniquement si un champs est valide, c'est mal amené de le chaîner du coup j'ai fait comme ça :
let nickNameDBChecking = null;
let emailDBChecking = null;
if(response["mail"]["valid"]){
emailDBChecking = DB_access.checkUserEmail(mail).then((result)=>{
if(result.length===0){
response["mail"]["available"]=true;
}
});
}
if(response["nickName"]["valid"]){
nickNameDBChecking = DB_access.checkUserNickname(nickName).then((result)=>{
if(result.length===0){
response["nickName"]["available"]=true;;
}
});
}
Promise.all([nickNameDBChecking,nickNameDBChecking]).then(()=>{
res.status(200).json(response);
});