我需要通过调用一个函数从“用户”集合中获取用户的ID,并返回它的值。
fetchId = (name) => {
User.findOne({name: name}, (err, user) => {
return user._id;
});
};
但是这个实现返回了null。如何修复它?
我需要通过调用一个函数从“用户”集合中获取用户的ID,并返回它的值。
fetchId = (name) => {
User.findOne({name: name}, (err, user) => {
return user._id;
});
};
按照您的示范,如果您不想使用承诺(promises),您可以从调用者传递一个回调函数,并在获取结果后调用回调函数,因为对Mongo的调用是异步的。
fetchId = (name, clb) => {
User.findOne({name: name}, (err, user) => {
clb(user._id);
});
};
fetchId("John", id => console.log(id));
fetchId = name => {
return User.findOne({name: name}).then(user => user.id);
};
fetchId("John")
.then(id => console.log(id));
async
并await
其结果...fetchId = async (name) => {
return User.findOne({name: name}).then(user => user.id);
};
let someId = await fetchId("John");
console.log(id)
编辑
对于对象中的任何方法(包括属性getter),只要是异步执行的,调用代码都需要注意并相应地采取行动。
这往往会向上扩散到依赖于调用者及其调用者等的系统中的所有内容。我们无法避免这种情况,也没有语法修复方案(语法是编译器看到的)。这是物理学:需要更长时间的事情就需要更长时间。我们可以使用语法部分隐藏复杂性,但我们仍然受到额外复杂性的限制。
将此应用于您的问题,假设我们有一个表示User的对象,该对象由mongo远程存储。最简单的方法是将内存中的用户对象视为未准备好,直到完成异步获取(findOne)操作。
在这种方法下,调用者只需要记住一件额外的事情:在使用未准备好的用户之前,让它准备好。以下代码采用了async / await样式语法,这是最现代化的语法风格,并且最大程度地隐藏 - 但不能消除:-(异步复杂性...
class MyMongoUser {
// after new, this in-memory user is not ready
constructor(name) {
this.name = name;
this.mongoUser = null; // optional, see how we're not ready?
}
// callers must understand: before using, tell it to get ready!
async getReady() {
this.mongoUser = await myAsyncMongoGetter();
// if there are other properties that are computed asynchronously, do those here, too
}
async myAsyncMongoGetter() {
// call mongo
const self = this;
return User.findOne({name: self.name}).then(result => {
// grab the whole remote object. see below
self.mongoUser = result;
});
}
// the remaining methods can be synchronous, but callers must
// understand that these won't work until the object is ready
mongoId() {
return (this.mongoUser)? this.mongoUser._id : null;
}
posts() {
return [ { creator_id: this.mongoId() } ];
}
}
注意,我们不仅仅是从用户那里获取mongo_id
,而是将整个mongo对象保存下来。除非这会占用大量内存,否则我们可以让它挂在那里,以便获取任何远程存储的属性。
以下是调用者的样子...
let joe = new MyMongoUser('joe');
console.log(joe.posts()) // isn't ready, so this logs [ { creator_id: null } ];
await joe.getReady();
console.log(joe.posts()) // logs [ { creator_id: 'the mongo id' } ];
return user._id
上面打印console.log(err)
吗? - Cata John