Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
javascript将我的身份验证功能转化为承诺_Javascript_Node.js_Callback_Promise - Fatal编程技术网

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')
    }
  });
}
这里发生了什么事