2017-09-26 1 views
1

J'ai une API Node.js avec un mongoDB. Il y a un chemin qui crée un utilisateur et doit hacher le mot de passe, pour cela j'utilise le paquetage bcryptjs.Node.js Mongoose Promise se perdant

l'itinéraire ressemble à ceci:

router.route('/user') 

    .post(function(req, res) { 
     if(req.body.password === req.body.passwordConfirm) { 
      userManager.addUser(req.body) 
       .then(function(response) { // waiting for the result of the mongoDB save 
        res.send({data:response}); 
       }); 
     } else { 
      res.send({err:'passwords do not match'}); 
     } 
    }) 

et userManager.addUSer:

this.addUser = function(userobject) { 
    bcrypt.genSalt(10, function(err, salt) { // generate a salt 
     if(err !== null) { 
      console.log(err); 
     } else { 
      bcrypt.hash(userobject.password_hash, salt, function(err, hash) { // hash pw 
       if(err !== null) { 
        console.log(err); 
       else { 
        userobject.password_hash = hash; // store hash in user obj 
        var user = new User(userobject); 
        return user.save().catch(function(err){ // save user in mongoDB 
         console.log(err); 
        }); 
       } 
      }); 
     } 
    }); 
}; 

Je reçois une erreur disant: "Impossible de lire la propriété 'puis' undefined", qui me dit que Je ne reçois pas de promesse d'addUser. J'ai regardé et bcryptjs malheureusement ne pas utiliser des promesses, cependant, Mangoose fait. (en ajoutant ceci:

var mongoose = require('mongoose').Promise = Promise; 

n'a pas aidé)

J'ai essayé envelopper la fonction dans une promesse de rejeter et de résoudre, mais qui donne cette erreur: « Erreur de type: résolveur Promesse non définie est pas une fonction ".

Comment puis-je obtenir la promesse que la fonction save() de mongoose retourne au .then() dans la route de publication? J'ai essayé d'ajouter le retour devant la fonction de deux bcrypt mais cela n'a pas fonctionné non plus.

Toutes les suggestions sont les bienvenues!

+0

Vous ne renvoyez pas de formulaire Promise votre 'this.addUser'. –

+1

pour être clair, vous ne retournez ** rien ** de 'this.addUser' –

+0

@Jaromanda X oui je vois que maintenant, je suis nouveau aux promesses et je pense que je me suis perdu par l'API qui ne supporte pas les promesses .. –

Répondre

1

Votre fonction addUser nevers renvoie la promesse à son appelant. Vous effectuez un return à partir de la fonction de rappel bcrypt.hash, mais cela n'a rien à voir avec la valeur de retour addUser.

Il semble que addUser doit utiliser des API non Promise activé, vous êtes coincé avec faire new Promise, quelque chose comme ça (voir les commentaires ***):

this.addUser = function(userobject) { 
    return new Promise(function(resolve, reject) { // *** 
     bcrypt.genSalt(10, function(err, salt) { // generate a salt 
      if(err !== null) { 
       reject(err);      // *** 
      } else { 
       bcrypt.hash(userobject.password_hash, salt, function(err, hash) { // hash pw 
        if(err !== null) { 
         reject(err);    // *** 
        else { 
         userobject.password_hash = hash; // store hash in user obj 
         var user = new User(userobject); 
         resolve(user.save());  // *** save user in mongoDB 
        } 
       }); 
      } 
     }); 
    }); 
}; 

Notez également que je don ne pas avoir addUser juste avaler des erreurs; à la place, ils sont propagés à l'appelant. L'appelant doit les gérer (même si "handling" ne fait que se connecter).

1

Vous ne renvoyez pas un formulaire Promesse votre this.addUser, vous devez convertir votre rappel basé sur bcrypt en Promises. Vous pouvez convertir l'intégralité de l'API bcrypt pour prendre en charge les fonctions basées sur Promise à l'aide, par exemple, de promisifyAll de la bibliothèque Bluebird, ou le faire manuellement à l'aide new Promise comme la façon suivante:

this.addUser = function(userobject) { 
    return new Promise((resolve, reject) => { 
     bcrypt.genSalt(10, (err, salt) => { 
     if (err) { 
      reject(err); 
     } else { 
      bcrypt.hash(userobject.password_hash, salt, function(err, hash) { 
      if (err) { 
       reject(err) 
      } else { 
       resolve(hash) 
      } 
      }) 
     } 
     }); 
    }) 
    .then(hash => { 
     userobject.password_hash = hash; // store hash in user obj 
     var user = new User(userobject); 
     return user.save() // save user in mongoDB 
    }) 
    .catch(function(err) { 
     console.log(err); 
    }); 
} 

Ou cette façon:

this.addUser = function(userobject) { 
    return new Promise((resolve, reject) => { 
     bcrypt.genSalt(10, (err, salt) => { 
     if (err) { 
      reject(err); 
     } else { 
      resolve(salt); 
     } 
     }); 
    }) 
    .then(salt => { 
     return new Promise((resolve, reject) => { 
     bcrypt.hash(userobject.password_hash, salt, function(err, hash) { 
      if (err) { 
      reject(err) 
      } else { 
      resolve(hash) 
      } 
     }) 
     }) 
    }) 
    .then(hash => { 
     userobject.password_hash = hash; // store hash in user obj 
     var user = new User(userobject); 
     return user.save() // save user in mongoDB 
    }) 
    .catch(function(err) { 
     console.log(err); 
    }); 
} 
0

Après avoir fait un peu plus creuser dans les journaux des modifications de bcryptjs j'ai découvert qu'ils ajouté des promesses mais n'a pas mis à jour la documentation. Les méthodes de hash de genSalt renvoient une promesse si les rappels sont omis. Cela se traduirait par:

this.addUser = function(userobject) { 
    return bcrypt.genSalt(10).then((salt) => { 
     return bcrypt.hash(userobject.password, salt).then((hash) => { 
      userobject.password_hash = hash; 
      var user = new User(userobject); 
      return user.save(); 
     }); 
    }); 
};