将参数传递给 Javascript/NodeJs 中的预定义回调
Passing parameters to predefined callbacks in Javascript/NodeJs
我正在尝试使用 bcrypt
扩展 NodeJs 后端的简单登录方法。我的问题是我现在需要通过散列步骤传递 user
变量。我当前的方法是这样的——当然 user
在 onPasswordHashed
:
的范围内是未定义的
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
包是否会在这里引起任何问题。处理回调链非常方便。
根据我的发现和测试,我可以覆盖回调,例如:
bcrypt.compare(req.body.password, user.password, this(user));
但有了这个,我当然会丢失有关 error
和 hash
的信息。
您可以使用可以直接访问父范围内变量的内联匿名回调,您可以使用 .bind()
向回调添加参数,或者在您的特定序列情况下,您可以保存 user
对象到更高范围的变量,以便后续回调可用。请参阅此示例中的 localUser
变量:
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);
}
},
...
);
},
仅供参考,如果您提供一些信息或 link 来记录 step()
函数的工作原理,可能还有一种方法可以将数据从一个步骤传递到下一个步骤。
假设step()
函数来自this module,你也可以这样做:
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);
}
},
...
);
},
传递给每个后续回调的 this
的值是一个通用函数对象,您可以将自己的属性附加到该对象。虽然这种方式看起来比以前的版本更简洁,但它实际上更危险一些,因为您添加到 this
对象的属性可能会与 step()
函数的内部实现中使用的内容发生冲突。第一个选项(父范围中的对象)是完全私有的,不会有可能的冲突。
现在进一步了解 step()
的工作原理,您可以使用 .bind()
将 user
对象添加到下一个回调参数,如下所示:
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);
}
},
...
);
},
我正在尝试使用 bcrypt
扩展 NodeJs 后端的简单登录方法。我的问题是我现在需要通过散列步骤传递 user
变量。我当前的方法是这样的——当然 user
在 onPasswordHashed
:
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
包是否会在这里引起任何问题。处理回调链非常方便。
根据我的发现和测试,我可以覆盖回调,例如:
bcrypt.compare(req.body.password, user.password, this(user));
但有了这个,我当然会丢失有关 error
和 hash
的信息。
您可以使用可以直接访问父范围内变量的内联匿名回调,您可以使用 .bind()
向回调添加参数,或者在您的特定序列情况下,您可以保存 user
对象到更高范围的变量,以便后续回调可用。请参阅此示例中的 localUser
变量:
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);
}
},
...
);
},
仅供参考,如果您提供一些信息或 link 来记录 step()
函数的工作原理,可能还有一种方法可以将数据从一个步骤传递到下一个步骤。
假设step()
函数来自this module,你也可以这样做:
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);
}
},
...
);
},
传递给每个后续回调的 this
的值是一个通用函数对象,您可以将自己的属性附加到该对象。虽然这种方式看起来比以前的版本更简洁,但它实际上更危险一些,因为您添加到 this
对象的属性可能会与 step()
函数的内部实现中使用的内容发生冲突。第一个选项(父范围中的对象)是完全私有的,不会有可能的冲突。
现在进一步了解 step()
的工作原理,您可以使用 .bind()
将 user
对象添加到下一个回调参数,如下所示:
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);
}
},
...
);
},