I'm building classes to find and quickly operate actions on mongodb documents. This is the UserCursor class. (Not talking about MongoDB's cursor)
exports { UserCursor };
class UserCursor {
private __id: object;
constructor(query: { _id?: object, otherId?: number }) {
let { _id, otherId } = query; // Shortens the vars' name
if (!_id && !otherId) return; // Checks if 1 identifier is provided
if (_id) { // If a _id is provided
Users.findOne({ _id }, (err, user) => {
this.__id = user._id;
});
} else if (otherId) { // If a otherId is provided
Users.findOne({ otherId }, (err, user) => {
console.log(1); // Debug, you'll see later
this.__id = user._id;
});
}
}
// Returns this.__id (which should have been initialized in the constructor)
get _id() {
console.log(2)
return this.__id;
}
}
When run, the console returns
2
1
I think you got the problem: the mongo callback in the constructor gets on after _id
operates. How could I manage that, since the constructor gets activated each time the class is used?
It's not entirely clear to me, what exactly you want to happen and how you use this class but I assume you want to instantiate it and then be able to get _id instantaneously. If it's not the case, you may still get some useful info from my answer. Feel free to provide more details, I will update it.
So mongodb operations are asynchronous, if you do
const cursor = new UserCursor(...)
console.log(cursor._id)
(I assume you want this), first all operations in this thread will run, including the call to get _id()
, then the callback code will. The problem with such asynchronous things is that now to use this _id you will have to make all of your code asynchronous as well.
So you will need to store a Promise that resolves with _id
from mongodb and make a method getId
that returns this promise like this:
private __id: Promise<object>
constructor(...) {
// ...
if(_id) {
this.__id = new Promise((resolve, reject) => {
Users.findOne({ _id }, (err, user) => {
if(err) return reject(err)
resolve(user._id)
});
})
} else {
// Same here
}
}
public getId() {
return this.__id;
}
Then use it:
const cursor = new UserCursor(...)
cursor.getId().then(_id => {
// Do smth with _id
})
Or
async function doStuff() {
const cursor = new UserCursor()
const _id = await cursor.getId()
}
doStuff()
If you now do it inside some function, you'll also have to make that function async
Also you could leave a getter like you have now, that will return a promise, but I find it less readable than getId()
:
cursor._id.then(_id => { ... })
const _id = await cursor._id