如何使用Mongoose虚拟属性中的异步代码?

Mik*_*y P 25 asynchronous mongoose node.js

我正在尝试将文档关联到不同的集合(不是嵌入式文档)中,虽然在Mongooose中存在问题,但我现在正试图通过延迟加载具有虚拟属性的关联文档来解决它. Mongoose网站.

问题是虚拟的getter将函数作为参数并使用虚拟属性的返回值.当虚拟不需要任何异步调用来计算它的值时,这很好,但是当我需要进行异步调用来加载其他文档时,它不起作用.这是我正在使用的示例代码:

TransactionSchema.virtual('notebook')
  .get( function() { // <-- the return value of this function is used as the property value
    Notebook.findById(this.notebookId, function(err, notebook) {
      return notebook; // I can't use this value, since the outer function returns before we get to this code
    })
    // undefined is returned here as the properties value
  });
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为函数在异步调用完成之前返回.有没有办法可以使用流控制库来完成这项工作,还是可以修改第一个函数,以便将findById调用传递给getter而不是匿名函数?

Jos*_*osh 21

您可以定义一个虚拟方法,您可以为其定义回调.

使用你的例子:

TransactionSchema.method('getNotebook', function(cb) {
  Notebook.findById(this.notebookId, function(err, notebook) {
    cb(notebook);
  })
});
Run Code Online (Sandbox Code Playgroud)

虽然唯一的评论者似乎是那些迂腐类型之一,但您也不应该害怕嵌入文档.它是我所理解的mongos强点之一.

一个人使用上面这样的代码:

instance.getNotebook(function(nootebook){
    // hey man, I have my notebook and stuff
});
Run Code Online (Sandbox Code Playgroud)

  • 但是有可能在虚拟中使用这种模式,以便TransactionSchema.virtual('notebook').get(function())调用方法'getNotebook'并返回结果吗?回调似乎不适用于该上下文. (2认同)
  • @格雷格,确实如此。虽然这是解决该问题的一个很好的解决方案,但并不是您真正需要的是异步虚拟字段。但我相信异步 getter/setter 在 JS 中是不可能的。 (2认同)

And*_*ner 5

虽然这解决了更广泛的问题而不是具体的问题,但我仍然认为值得提交:

您可以使用Mongoose的查询填充函数轻松地从另一个集合中加载相关文档(具有与定义虚拟几乎相同的结果).使用上面的示例,这需要在Transaction模式中指定ObjectID的ref (指向Notebook集合),然后populate(NotebookId)在构造查询时调用.链接的Mongoose文档非常彻底地解决了这个问题.

我不熟悉Mongoose的历史,但我猜populate这些早期的答案提交时我们不存在.