2017-09-26 75 views
1

我有一個Node.js API和mongoDB。有一條路由創建一個用戶並需要散列密碼,爲此我使用bcryptjs軟件包。Node.js Mongoose Promise迷失

的路線是這樣的:

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'}); 
     } 
    }) 

和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); 
        }); 
       } 
      }); 
     } 
    }); 
}; 

我得到一個錯誤說: 「不能讀取屬性 '然後' 未定義」,它告訴我,我沒有收到addUser的承諾。我看着bcryptjs悲傷地不使用承諾,但是,貓鼬的確如此。 (添加此:

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

沒有幫助)

我試圖在拒絕和解決一個承諾包裝的功能,但它給出了這個錯誤:「類型錯誤:無極解析器未定義不是一個函數」。

如何獲得mongoose的save()函數返回到post過程中的.then()的承諾?我試圖在兩個bcrypt函數前添加return,但是這也不起作用。

歡迎任何建議!

+0

您不會從您的'this.addUser'返回一個Promise窗體。 –

+1

要清楚,你不會從'this.addUser'返回任何** ** –

+0

@Jaromanda X是的,我現在看到,我對承諾是新的,我認爲我失去了API,不支持承諾.. –

回答

1

您的addUser函數nevers返回對其調用者的承諾。您正在從bcrypt.hash回調函數中執行return,但這與addUser的返回值無關。

看起來addUser必須使用一些支持非承諾的API,讓你堅持做new Promise,這樣的事情(見***評論):

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 
        } 
       }); 
      } 
     }); 
    }); 
}; 

另外請注意,我不沒有addUser只是吞嚥錯誤;相反,他們傳播給調用者。調用者應該處理它們(即使「處理」只是記錄)。

1

您不會從this.addUser返回Promise表單,您必須將基於bcrypt的回撥轉換爲Promises。您可以將整個bcrypt API轉換爲支持基於Promise的功能,例如使用藍鳥庫promisifyAll,或做手工用new Promise像這樣:

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); 
    }); 
} 

還是那個樣子:

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

做一些更bcryptjs的更改日誌挖掘後,我發現他們添加的承諾,但沒有更新文檔..如果省略了回調,genSalt和散列方法將返回一個承諾。這將轉化爲:

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(); 
     }); 
    }); 
};