将parameter passing给Javascript / NodeJs中的预定义callback

我试图用bcrypt扩展我的简单的NodeJs后端的login方法。 我的问题是,我现在需要通过散列步骤传递uservariables。 我当前的方法是这样的 – 自然, useronPasswordHashed范围内是未定义的:

 signin : function(req, res, next) { step ( function findUser() { User.findOne({ "email": req.body.email }, this); }, function onResultReceived(error, user) { if (error) { ... } else { if (user) { bcrypt.compare(req.body.password, user.password, this); } else { ... } } }, function onPasswordHashed(error, hash) { if (error) { ... } else { bcrypt.compare(user.password, hash, this); // user is undefined here } }, ... ); }, 

原则上我可以:(a)使用bcrypt的同步调用。 但是,在某些时候,我可能会遇到同样的问题,没有可用的同步函数调用。 (b)我可以首先定义var userObj = null ,并在onResultReceived方法中设置userObj = user 。 那么userObj应该在所有范围内都可见。 但这似乎并不是最佳做法。 还是呢?

从目前来看,使用bind()似乎是一种可行的方式。 我只是不知道如何将它应用到我的头上。 例如:

 bcrypt.compare(req.body.password, user.password, this.bind({user: user})); 

不起作用。 我不知道这个step包是否会在这里引起任何问题。 处理callback链非常方便。

编辑:链接到step包文档: npm , github

从我发现和testing的,我可以覆盖callback,例如:

 bcrypt.compare(req.body.password, user.password, this(user)); 

但有了这个,我当然会得到有关errorhash

你可以使用一个内联的匿名callback函数,它可以直接访问父variables的variables,你可以使用.bind()向callback函数中添加参数,或者在你的特定顺序情况下,你可以将user对象保存到一个更高范围的variables中它可用于后续的callback。 在这个例子中看到localUservariables:

 signin : function(req, res, next) { var localUser; step ( function findUser() { User.findOne({ "email": req.body.email }, this); }, function onResultReceived(error, user) { // save user variable to higher scoped variable so // subsequent callbacks can access it localUser = user; if (error) { ... } else { if (user) { bcrypt.compare(req.body.password, user.password, this); } else { ... } } }, function onPasswordHashed(error, hash) { if (error) { ... } else { // use localUser from higher scope here that was set by a previous // step in the process bcrypt.compare(localUser.password, hash, this); } }, ... ); }, 

仅供参考,如果您提供了关于step()函数如何工作的一些信息或链接,可能还有一种方法可以将数据从一个步骤传递到下一个步骤。


假设step()函数来自这个模块 ,你也可以这样做:

 signin : function(req, res, next) { step ( function findUser() { User.findOne({ "email": req.body.email }, this); }, function onResultReceived(error, user) { // save user on our stepper object so it can be accessed by later callbacks this.user = user; if (error) { ... } else { if (user) { bcrypt.compare(req.body.password, user.password, this); } else { ... } } }, function onPasswordHashed(error, hash) { if (error) { ... } else { // use this.user that was set by a previous // step in the process bcrypt.compare(this.user, hash, this); } }, ... ); }, 

传递给每个连续callback的this值是一个常用的函数对象,你可以附加你自己的属性。 虽然这种看起来比以前的版本更清洁,但实际上它更危险一点,因为添加this对象的属性可能与step()函数的内部实现中使用的内容相冲突。 第一个选项(父范围中的对象)是完全私有的,不会有可能的冲突。


现在了解更多关于step()工作方式,可以使用.bind()user对象添加到下一个callback参数中,如下所示:

 signin : function(req, res, next) { step ( function findUser() { User.findOne({ "email": req.body.email }, this); }, function onResultReceived(error, user) { // save user on our stepper object so it can be accessed by later callbacks if (error) { ... } else { if (user) { // prepend user to the callback arguments for the next callback bcrypt.compare(req.body.password, user.password, this.bind(this, user)); } else { ... } } }, function onPasswordHashed(user, error, hash) { // user is passed in here from previous callback if (error) { ... } else { // use this.user that was set by a previous // step in the process bcrypt.compare(user, hash, this); } }, ... ); },