javascript将我的身份验证功能转化为承诺
下面是我用来检查用户是否经过身份验证的访问函数的示例javascript将我的身份验证功能转化为承诺,javascript,node.js,callback,promise,Javascript,Node.js,Callback,Promise,下面是我用来检查用户是否经过身份验证的访问函数的示例 access = function(id, user_id, callback) { docs.findOne({ _id: id }, function(err, doc) { if (doc.user.indexOf(user_id) != -1) { callback("authenticated") } else { callback(); } }); } 我使用它
access = function(id, user_id, callback) {
docs.findOne({
_id: id
}, function(err, doc) {
if (doc.user.indexOf(user_id) != -1) {
callback("authenticated")
} else {
callback();
}
});
}
我使用它作为回调模式,如下所示
access(id, user, function (status) {
if (status == 'authenticated') doSomething()
})
我发现写起来有点无聊,因为每次使用access函数时都需要检查回调状态。我希望有一种更好的方法来使用access函数,以便在回调上假定身份验证。像这样的
access(id, user, function () {
doSomething()
}).err(function () {
doSomethingElse()
})
让我们分开:
access(id, user, function () {
doSomething()
}).err(function () {
doSomethingElse()
});
意思与
var ret = access(id, user, function () {
doSomething()
});
ret.err(function () {
doSomethingElse()
})
所以,err(…)
会一直被调用,而不是你想要的
那怎么办
var Access = function ()
{
this.errorHandler = null;
this.registerErrorHandler = function (errh)
{
this.errorHandler = errh;
...
this.authenticate = function (...)
{
// if not authenticated
this.errorHandler(....)
只是个主意?this.errorHandler也可以是一个处理程序数组,等等
要调用该命令,您需要执行以下操作:
myAccess = new Access();
myAccess.registerErrorHandler(xyz);
myAccess.authenticate(.....);
让我们分开:
access(id, user, function () {
doSomething()
}).err(function () {
doSomethingElse()
});
意思与
var ret = access(id, user, function () {
doSomething()
});
ret.err(function () {
doSomethingElse()
})
所以,err(…)
会一直被调用,而不是你想要的
那怎么办
var Access = function ()
{
this.errorHandler = null;
this.registerErrorHandler = function (errh)
{
this.errorHandler = errh;
...
this.authenticate = function (...)
{
// if not authenticated
this.errorHandler(....)
只是个主意?this.errorHandler也可以是一个处理程序数组,等等
要调用该命令,您需要执行以下操作:
myAccess = new Access();
myAccess.registerErrorHandler(xyz);
myAccess.authenticate(.....);
我相信Mongoose会为它的所有查询函数返回承诺,所以我认为下面这样的方法是可行的:
var access = function(id, user_id, callback) {
return docs.findOne({_id: id}).then(function (doc) {
if (doc.user.indexOf(user_id) != -1) throw(new Error("Wrong user_id."))
}) // not handling any errors here
}
然后您可以这样使用它:
access(id, user).then(function () {
doSomething()
}, function (error) { // this "onRejected" handler is called when findOne fails,
console.log(error) // or if user_id doesn't match
doSomethingElse() // maybe decide what to do based on the type of error?
})
如果您使用的不是Mongoose,而是“原生”MongoDB客户机,那么您首先需要自己创建一个承诺。有很多图书馆可以这样做。我建议您寻找符合Promises/a+标准的库。大多数都很容易识别,因为他们的主页(或自述文件)上显著地有一个写着“then”的黄色方框。我相信Mongoose会为其所有查询功能返回承诺,所以我认为以下类似的功能会起作用:
var access = function(id, user_id, callback) {
return docs.findOne({_id: id}).then(function (doc) {
if (doc.user.indexOf(user_id) != -1) throw(new Error("Wrong user_id."))
}) // not handling any errors here
}
然后您可以这样使用它:
access(id, user).then(function () {
doSomething()
}, function (error) { // this "onRejected" handler is called when findOne fails,
console.log(error) // or if user_id doesn't match
doSomethingElse() // maybe decide what to do based on the type of error?
})
如果您使用的不是Mongoose,而是“原生”MongoDB客户机,那么您首先需要自己创建一个承诺。有很多图书馆可以这样做。我建议您寻找符合Promises/a+标准的库。大多数都很容易识别,因为他们的主页(或自述文件)上显著地有一个黄色方框,上面写着“then”。如果你想用半小时的视频形式介绍承诺,我建议我在JSConf.eu上的演讲: 我从你的问题中得到的印象是,你以前没有真正看过承诺(以及其他一些并非所有人都看过的答案) 规范中定义了JavaScript承诺。它很容易阅读,值得一看。并非所有承诺都遵循此规范(jQuery是唯一值得注意的例外),但您可以找到一个兼容实现的列表 作为新来者: 如果您想了解承诺是如何实现的,它是最简单的一种(它的性能也是最快的)。免责声明:这是我写的 承诺是极其有限的,所以如果没有大量的扩展,它就没有多大的用处。我建议你从一开始就使用它,因为它是最受欢迎的产品之一,并且有很多功能,可以让你更简单地使用它。Q也最符合未来规范中的大多数思想 如果您使用Mongoose作为数据库驱动程序,它自带Promises/A+的实现,因此您可以使用它:
access = function(id, user_id) {
return docs.findOne({
_id: id
})
.then(function(doc) {
if (doc.user.indexOf(user_id) == -1) {
throw new Error('User Not Found')
}
});
}
这里发生的事情是,docs.findOne
正在返回一个“承诺”,因为它是在没有回调的情况下调用的。由附加的处理程序,然后添加回调。它还返回一个新承诺,第一个承诺中的任何错误都会自动传播到新承诺。如果回调中抛出错误,则新承诺将被“拒绝”。如果回调返回一个值,那么新的承诺将用该值“实现”
这样定义了我们的函数后,我们可以将其称为:
access(id, user_id)
.then(function () {
doSomething();
});
如果在某个时候我们想要处理该错误,我们可以通过附加错误处理程序来实现:
access(id, user)
.then(function () {
doSomething()
}, function (err) {
doSomethingElse()
})
唯一的问题是,如果doSomething
抛出一个错误,它将被静音(这很糟糕)。如果你已经完成了链接。那么
会要求承诺你需要结束该链接
如果你正在使用猫鼬内置的承诺,那么你会打电话给猫鼬
如果你使用Q承诺,那么你会打电话给
如果您想将猫鼬承诺转换为Q承诺,只需将其传递给Q
:
Q(access(id, user))
.then(function () {
doSomething()
}, function (err) {
doSomethingElse()
})
.done();
如果你没有用猫鼬
如果您没有使用Mongoose,并且需要从头开始创建一个Q承诺,那么您可以使用它
还有一个处理节点样式API的快捷方式:
var findOne = Q.denodeify(docs.findOne);
var promise = findOne({_id: id});
设计推理
最后,如果你想知道为什么承诺会像他们那样工作,或者你认为他们的设计在某种程度上是愚蠢的,这是一个很好的指南。它将带您从头开始开发承诺库,从您认为“回调还不够好”的地方开始,一直到完整承诺库。如果您想以视频形式介绍承诺半小时,我建议您在JSConf.eu上发表演讲:
我从你的问题中得到的印象是,你以前没有真正看过承诺(以及其他一些并非所有人都看过的答案)
规范中定义了JavaScript承诺。它很容易阅读,值得一看。并非所有承诺都遵循此规范(jQuery是唯一值得注意的例外),但您可以找到一个兼容实现的列表
作为新来者:
如果您想了解承诺是如何实现的,它是最简单的一种(它的性能也是最快的)。免责声明:这是我写的
承诺是极其有限的,所以如果没有大量的扩展,它就没有多大的用处。我建议你从一开始就使用它,因为它是最受欢迎的产品之一,并且有很多功能,可以让你更简单地使用它。Q也最符合未来规范中的大多数思想
如果您使用Mongoose作为数据库驱动程序,它自带Promises/A+的实现,因此您可以使用它:
access = function(id, user_id) {
return docs.findOne({
_id: id
})
.then(function(doc) {
if (doc.user.indexOf(user_id) == -1) {
throw new Error('User Not Found')
}
});
}
这里发生了什么事