是否有可能使一个asynchronous函数返回一个mongoose查询而不是一个承诺?

build立

假设我们有一些文件FooBarFoo有一个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); 

现在假设我们有一个Foo文件的name ,但不是它的_id 。 我们想find所有引用Foo文档的Bar文档。 所以我们编写一个函数,首先find具有给定nameFoo文档,然后使用它来查找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'); 

问题

不过,我们也想按datesortingbars 。 通常,使用mongoose的查询生成器,我们可以这样写:

 let bars = await Bar.find({}) .sort('date'); 

但是,如果我们使用我们写的函数:

 let bars = await Bar.findBarWithFooName('fooName') .sort('date'); 

我们会得到一个错误:

UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝id:1):TypeError:Bar.findBarWithFooName(…)。sort不是一个函数

debugging

通过调查console.log(bars) ,我发现当我们调用Bar.find({}) ,生成的对象是mongoose的Query对象。

但是,当我们调用Bar.findBarWithFooName('fooName') ,生成的对象是Promise { <pending> } 。 因此,在Promise { <pending> }上不存在方法sort是有意义的。

那么我的问题是,为什么在第一种情况下,它返回一个Query ,但在第二种情况下,它返回一个Promise { <pending> } ? 我能做些什么来使findBarWithFooName返回一个Query以便我可以继续构build查询,而不是Promise { <pending> }

我知道我可以使用的一个解决scheme是从await Foo.findOne({ name: name })取出await Foo.findOne({ name: name }) ,只需要一个_id作为参数而不是name 。 但是,我试图抽象出先find一个Foo的过程,这就是为什么我要创build一个返回Query的单个函数。

没有

使一个async function返回一个自定义对象而不是一个Promise是不可能的 – 甚至不是一个promise子类。

没有

你不能让findBarWithFooName返回一个查询,因为在Bar.find被调用之前它必须等待Foo.findOne ,并构造你正在查找的Query对象。

为了解决你的问题,你将需要返回一些包装的查询 – 你不能直接return查询,因为它是可以的,并得到隐含等待。 电话会看起来像

 let bars = await ( unwrap(await Bar.findBarWithFooName('fooName')).sort('date') ); 

unwrap是将Query从包装中取出的东西。 作为一个包装,你可以使用任何东西,而无需使用then方法 – 它可以是一个闭包,一个具有属性的对象,一个具有单个元素的数组。