我们假设我们有一些文件Foo
和Bar
。 Foo
有一个name
字段,可用于识别除使用文档_id
之外的其他文档。 Bar
包含对Foo
文档的引用。
const fooSchema = new mongoose.Schema({
name: {
type: String,
unique: true
}
});
const Foo = <any>mongoose.model<any>('Foo', fooSchema);
const barSchema = new mongoose.Schema({
foo: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Foo'
},
date: Date
});
const Bar = <any>mongoose.model<any>('Bar', barSchema);
现在假设我们有name
个Foo
文档,但不是_id
。我们希望查找引用Bar
文档的所有Foo
文档。因此,我们编写一个函数,首先找到具有给定Foo
的{{1}}文档,然后使用它来查找name
文档。
Bar
我们可以通过写:
来使用这个功能barSchema.statics.findBarWithFooName = async function(name: string) {
let foo = await Foo.findOne({ name: name });
return Bar.find({ foo: foo });
};
但是,我们还想按日期对let bars = await Bar.findBarWithFooName('fooName');
进行排序。通常,使用mongoose的“查询”构建器,我们可以编写如下内容:
bars
但是,如果我们改为使用我们写的函数:
let bars = await Bar.find({})
.sort('date');
我们会收到错误:
UnhandledPromiseRejectionWarning:未处理的承诺 rejection(拒绝id:1):TypeError: Bar.findBarWithFooName(...)。sort不是函数
在调查let bars = await Bar.findBarWithFooName('fooName')
.sort('date');
时,我发现当我们调用console.log(bars)
时,生成的对象是猫鼬的Bar.find({})
对象。
但是,当我们调用Query
时,生成的对象为Bar.findBarWithFooName('fooName')
。因此,Promise { <pending> }
上的sort
方法不存在是有道理的。
我的问题是,为什么在第一种情况下,它会返回Promise { <pending> }
,但在第二种情况下,它会返回Query
?我可以做些什么让Promise { <pending> }
返回findBarWithFooName
,以便我可以继续构建查询,而不是Query
?
我知道我可以使用的一个解决方案是从Promise { <pending> }
中取出await Foo.findOne({ name: name })
,只需将findBarWithFooName
作为参数而不是_id
。但是,我试图抽象出必须首先找到name
的过程,这就是我尝试创建一个返回Foo
的函数的原因。
答案 0 :(得分:2)
不可能让async function
返回自定义对象而不是Promise
- 甚至不是promise子类。
您无法让findBarWithFooName
返回查询,因为在Foo.findOne
被调用之前必须等待Bar.find
并构建您正在查找的查询对象。
要解决您的问题,您需要为查询返回一些包装器 - 您不能直接return
查询,因为它可以直接查询并且会被隐式等待。然后呼叫看起来像
let bars = await ( unwrap(await Bar.findBarWithFooName('fooName')).sort('date') );
unwrap
是将查询从包装器中取出的东西。作为包装器,您可以使用没有then
方法的任何东西 - 它可以是闭包,具有属性的对象,具有单个元素的数组......