Mongodb findOne - return value [duplicate]












0















This question already has an answer here:




  • How do I return the response from an asynchronous call?

    33 answers




I need to fetch id of user from collection 'users' by calling a function and return it's value.



fetchId = (name) => {
User.findOne({name: name}, (err, user) => {
return user._id;
});
};


But this implementation returns null. What is the way to fix it?










share|improve this question













marked as duplicate by JohnnyHK javascript
Users with the  javascript badge can single-handedly close javascript questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 15 at 16:38


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.















  • Is any error triggered? Can you console.log(err) above the return user._id?
    – Cata John
    Nov 13 at 18:17










  • console.log response good id value, return - not.
    – Adam Jakś
    Nov 13 at 19:25
















0















This question already has an answer here:




  • How do I return the response from an asynchronous call?

    33 answers




I need to fetch id of user from collection 'users' by calling a function and return it's value.



fetchId = (name) => {
User.findOne({name: name}, (err, user) => {
return user._id;
});
};


But this implementation returns null. What is the way to fix it?










share|improve this question













marked as duplicate by JohnnyHK javascript
Users with the  javascript badge can single-handedly close javascript questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 15 at 16:38


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.















  • Is any error triggered? Can you console.log(err) above the return user._id?
    – Cata John
    Nov 13 at 18:17










  • console.log response good id value, return - not.
    – Adam Jakś
    Nov 13 at 19:25














0












0








0








This question already has an answer here:




  • How do I return the response from an asynchronous call?

    33 answers




I need to fetch id of user from collection 'users' by calling a function and return it's value.



fetchId = (name) => {
User.findOne({name: name}, (err, user) => {
return user._id;
});
};


But this implementation returns null. What is the way to fix it?










share|improve this question














This question already has an answer here:




  • How do I return the response from an asynchronous call?

    33 answers




I need to fetch id of user from collection 'users' by calling a function and return it's value.



fetchId = (name) => {
User.findOne({name: name}, (err, user) => {
return user._id;
});
};


But this implementation returns null. What is the way to fix it?





This question already has an answer here:




  • How do I return the response from an asynchronous call?

    33 answers








javascript node.js mongodb






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 13 at 18:10









Adam Jakś

45




45




marked as duplicate by JohnnyHK javascript
Users with the  javascript badge can single-handedly close javascript questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 15 at 16:38


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.






marked as duplicate by JohnnyHK javascript
Users with the  javascript badge can single-handedly close javascript questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
Nov 15 at 16:38


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.














  • Is any error triggered? Can you console.log(err) above the return user._id?
    – Cata John
    Nov 13 at 18:17










  • console.log response good id value, return - not.
    – Adam Jakś
    Nov 13 at 19:25


















  • Is any error triggered? Can you console.log(err) above the return user._id?
    – Cata John
    Nov 13 at 18:17










  • console.log response good id value, return - not.
    – Adam Jakś
    Nov 13 at 19:25
















Is any error triggered? Can you console.log(err) above the return user._id?
– Cata John
Nov 13 at 18:17




Is any error triggered? Can you console.log(err) above the return user._id?
– Cata John
Nov 13 at 18:17












console.log response good id value, return - not.
– Adam Jakś
Nov 13 at 19:25




console.log response good id value, return - not.
– Adam Jakś
Nov 13 at 19:25












2 Answers
2






active

oldest

votes


















2














following your example, if you don't want to use promises, you can simply pass a callback from the caller and invoke the callback when you have the result since the call to mongo is asynchronous.



fetchId = (name, clb) => {
User.findOne({name: name}, (err, user) => {
clb(user._id);
});
};

fetchId("John", id => console.log(id));


Otherwise you can use the promise based mechanism omitting the first callback and return the promise to the caller.



fetchId = name => {
return User.findOne({name: name}).then(user => user.id);
};


fetchId("John")
.then(id => console.log(id));





share|improve this answer





















  • Ok, but how to use this first snippet with return value syntax? Ex. { creator_id: fetchId("Ian Corby", id => { /* return id */ } ) }
    – Adam Jakś
    Nov 13 at 19:28












  • @AdamJakś - there are only two things that can be returned from a function (fetchId) whose result depends on an async call (findOne): (a) nothing, which is what your code and this answer's first idea returns, (b) a promise, which is this answer's second suggestion.
    – danh
    Nov 13 at 20:21










  • @AdamJakś the promise suggestion is better, and once you master it, read up on async/away, which is a small improvement to promise that allows you to use the syntax I think you're looking for.
    – danh
    Nov 13 at 20:22










  • @Karim from where you get user in user => user.id snippet? (second example) ;)
    – Adam Jakś
    Nov 15 at 12:44












  • it's the result of the promise returned by User.findOne , after the call to the database
    – Karim
    Nov 15 at 12:46



















0














A third way is a variation of suggestion #2 in @Karim's (perfectly good) answer. If the OP wants to code it as if results are being assigned from async code, an improvement would be to declare fetchId as async and await its result...



fetchId = async (name) => {
return User.findOne({name: name}).then(user => user.id);
};

let someId = await fetchId("John");
console.log(id)


edit



For any method on an object -- including a property getter -- that works asynchronously, the calling code needs to be aware and act accordingly.



This tends to spread upward in your system to anything that depends on caller's callers, and so on. We can't avoid this, and there's no syntactic fix (syntax is what the compiler sees). It's physics: things that take longer, just take longer. We can use syntax to partially conceal the complexity, but we're stuck with the extra complexity.



Applying this to your question, say we have an object representing a User which is stored remotely by mongo. The simplest approach is to think of the in-memory user object as unready until an async fetch (findOne) operation has completed.



Under this approach, the caller has just one extra thing to remember: tell the unready user to get ready before using it. The code below employs async/await style syntax which is the the most modern and does the most to conceal -- but not eliminate :-( -- the async complexity...



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() } ];
}
}


Notice, instead of just grabbing the mongo _id from the user, we put away the whole mongo object. Unless this is a huge memory hog, we might as well have it hanging around so we can get any of the remotely stored properties.



Here's what the caller looks like...



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' } ];





share|improve this answer























  • Yes, but the problem is I need to implement sytax like that: value = fetchId('John'); so function fetchId should RETURN value (console.log is working properly, but return - not) ;)
    – Adam Jakś
    Nov 14 at 13:15












  • @AdamJakś - it can only return nothing or a promise to finish later. What it can't return is the result of findOne(), which hasn't run yet at the point fetchId returns. In the callback approach, it doesn't matter what the callback returns. The call back is called after findOne() runs.
    – danh
    Nov 14 at 15:45










  • Ok, thank You for the explicit explaining. But - what if I need to use this function in value of property in Object? Just like: { posts [ { content: 'lorem', creator_id: <fetchId function use> } ]. Do You think it is possible? How to give the creator_id key the user id value? ;)
    – Adam Jakś
    Nov 15 at 8:03










  • @AdamJakś - I understand what's troubling you. Please see the extensive amendment I made to the answer.
    – danh
    Nov 15 at 16:56












  • Thanks you a lot for great explaining. I implemented this code by adding a function to value property, just like: posts:[ { creator_id: fetchId('john'); } ] and in the function body I added code from your caller's code proposition: async fetchId(name) { let john = new MyMongoUser(name); await john.getReady(); john.mongoId(); } And the problem is now that console returns me an error: Post validation failed: creator_id: Cast to String failed for value "Promise { <pending> }" at path "creat or_id" In post schema I have creator_id set as string. Parse string is not a sollution.
    – Adam Jakś
    Nov 16 at 12:14




















2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














following your example, if you don't want to use promises, you can simply pass a callback from the caller and invoke the callback when you have the result since the call to mongo is asynchronous.



fetchId = (name, clb) => {
User.findOne({name: name}, (err, user) => {
clb(user._id);
});
};

fetchId("John", id => console.log(id));


Otherwise you can use the promise based mechanism omitting the first callback and return the promise to the caller.



fetchId = name => {
return User.findOne({name: name}).then(user => user.id);
};


fetchId("John")
.then(id => console.log(id));





share|improve this answer





















  • Ok, but how to use this first snippet with return value syntax? Ex. { creator_id: fetchId("Ian Corby", id => { /* return id */ } ) }
    – Adam Jakś
    Nov 13 at 19:28












  • @AdamJakś - there are only two things that can be returned from a function (fetchId) whose result depends on an async call (findOne): (a) nothing, which is what your code and this answer's first idea returns, (b) a promise, which is this answer's second suggestion.
    – danh
    Nov 13 at 20:21










  • @AdamJakś the promise suggestion is better, and once you master it, read up on async/away, which is a small improvement to promise that allows you to use the syntax I think you're looking for.
    – danh
    Nov 13 at 20:22










  • @Karim from where you get user in user => user.id snippet? (second example) ;)
    – Adam Jakś
    Nov 15 at 12:44












  • it's the result of the promise returned by User.findOne , after the call to the database
    – Karim
    Nov 15 at 12:46
















2














following your example, if you don't want to use promises, you can simply pass a callback from the caller and invoke the callback when you have the result since the call to mongo is asynchronous.



fetchId = (name, clb) => {
User.findOne({name: name}, (err, user) => {
clb(user._id);
});
};

fetchId("John", id => console.log(id));


Otherwise you can use the promise based mechanism omitting the first callback and return the promise to the caller.



fetchId = name => {
return User.findOne({name: name}).then(user => user.id);
};


fetchId("John")
.then(id => console.log(id));





share|improve this answer





















  • Ok, but how to use this first snippet with return value syntax? Ex. { creator_id: fetchId("Ian Corby", id => { /* return id */ } ) }
    – Adam Jakś
    Nov 13 at 19:28












  • @AdamJakś - there are only two things that can be returned from a function (fetchId) whose result depends on an async call (findOne): (a) nothing, which is what your code and this answer's first idea returns, (b) a promise, which is this answer's second suggestion.
    – danh
    Nov 13 at 20:21










  • @AdamJakś the promise suggestion is better, and once you master it, read up on async/away, which is a small improvement to promise that allows you to use the syntax I think you're looking for.
    – danh
    Nov 13 at 20:22










  • @Karim from where you get user in user => user.id snippet? (second example) ;)
    – Adam Jakś
    Nov 15 at 12:44












  • it's the result of the promise returned by User.findOne , after the call to the database
    – Karim
    Nov 15 at 12:46














2












2








2






following your example, if you don't want to use promises, you can simply pass a callback from the caller and invoke the callback when you have the result since the call to mongo is asynchronous.



fetchId = (name, clb) => {
User.findOne({name: name}, (err, user) => {
clb(user._id);
});
};

fetchId("John", id => console.log(id));


Otherwise you can use the promise based mechanism omitting the first callback and return the promise to the caller.



fetchId = name => {
return User.findOne({name: name}).then(user => user.id);
};


fetchId("John")
.then(id => console.log(id));





share|improve this answer












following your example, if you don't want to use promises, you can simply pass a callback from the caller and invoke the callback when you have the result since the call to mongo is asynchronous.



fetchId = (name, clb) => {
User.findOne({name: name}, (err, user) => {
clb(user._id);
});
};

fetchId("John", id => console.log(id));


Otherwise you can use the promise based mechanism omitting the first callback and return the promise to the caller.



fetchId = name => {
return User.findOne({name: name}).then(user => user.id);
};


fetchId("John")
.then(id => console.log(id));






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 13 at 18:20









Karim

4,6041719




4,6041719












  • Ok, but how to use this first snippet with return value syntax? Ex. { creator_id: fetchId("Ian Corby", id => { /* return id */ } ) }
    – Adam Jakś
    Nov 13 at 19:28












  • @AdamJakś - there are only two things that can be returned from a function (fetchId) whose result depends on an async call (findOne): (a) nothing, which is what your code and this answer's first idea returns, (b) a promise, which is this answer's second suggestion.
    – danh
    Nov 13 at 20:21










  • @AdamJakś the promise suggestion is better, and once you master it, read up on async/away, which is a small improvement to promise that allows you to use the syntax I think you're looking for.
    – danh
    Nov 13 at 20:22










  • @Karim from where you get user in user => user.id snippet? (second example) ;)
    – Adam Jakś
    Nov 15 at 12:44












  • it's the result of the promise returned by User.findOne , after the call to the database
    – Karim
    Nov 15 at 12:46


















  • Ok, but how to use this first snippet with return value syntax? Ex. { creator_id: fetchId("Ian Corby", id => { /* return id */ } ) }
    – Adam Jakś
    Nov 13 at 19:28












  • @AdamJakś - there are only two things that can be returned from a function (fetchId) whose result depends on an async call (findOne): (a) nothing, which is what your code and this answer's first idea returns, (b) a promise, which is this answer's second suggestion.
    – danh
    Nov 13 at 20:21










  • @AdamJakś the promise suggestion is better, and once you master it, read up on async/away, which is a small improvement to promise that allows you to use the syntax I think you're looking for.
    – danh
    Nov 13 at 20:22










  • @Karim from where you get user in user => user.id snippet? (second example) ;)
    – Adam Jakś
    Nov 15 at 12:44












  • it's the result of the promise returned by User.findOne , after the call to the database
    – Karim
    Nov 15 at 12:46
















Ok, but how to use this first snippet with return value syntax? Ex. { creator_id: fetchId("Ian Corby", id => { /* return id */ } ) }
– Adam Jakś
Nov 13 at 19:28






Ok, but how to use this first snippet with return value syntax? Ex. { creator_id: fetchId("Ian Corby", id => { /* return id */ } ) }
– Adam Jakś
Nov 13 at 19:28














@AdamJakś - there are only two things that can be returned from a function (fetchId) whose result depends on an async call (findOne): (a) nothing, which is what your code and this answer's first idea returns, (b) a promise, which is this answer's second suggestion.
– danh
Nov 13 at 20:21




@AdamJakś - there are only two things that can be returned from a function (fetchId) whose result depends on an async call (findOne): (a) nothing, which is what your code and this answer's first idea returns, (b) a promise, which is this answer's second suggestion.
– danh
Nov 13 at 20:21












@AdamJakś the promise suggestion is better, and once you master it, read up on async/away, which is a small improvement to promise that allows you to use the syntax I think you're looking for.
– danh
Nov 13 at 20:22




@AdamJakś the promise suggestion is better, and once you master it, read up on async/away, which is a small improvement to promise that allows you to use the syntax I think you're looking for.
– danh
Nov 13 at 20:22












@Karim from where you get user in user => user.id snippet? (second example) ;)
– Adam Jakś
Nov 15 at 12:44






@Karim from where you get user in user => user.id snippet? (second example) ;)
– Adam Jakś
Nov 15 at 12:44














it's the result of the promise returned by User.findOne , after the call to the database
– Karim
Nov 15 at 12:46




it's the result of the promise returned by User.findOne , after the call to the database
– Karim
Nov 15 at 12:46













0














A third way is a variation of suggestion #2 in @Karim's (perfectly good) answer. If the OP wants to code it as if results are being assigned from async code, an improvement would be to declare fetchId as async and await its result...



fetchId = async (name) => {
return User.findOne({name: name}).then(user => user.id);
};

let someId = await fetchId("John");
console.log(id)


edit



For any method on an object -- including a property getter -- that works asynchronously, the calling code needs to be aware and act accordingly.



This tends to spread upward in your system to anything that depends on caller's callers, and so on. We can't avoid this, and there's no syntactic fix (syntax is what the compiler sees). It's physics: things that take longer, just take longer. We can use syntax to partially conceal the complexity, but we're stuck with the extra complexity.



Applying this to your question, say we have an object representing a User which is stored remotely by mongo. The simplest approach is to think of the in-memory user object as unready until an async fetch (findOne) operation has completed.



Under this approach, the caller has just one extra thing to remember: tell the unready user to get ready before using it. The code below employs async/await style syntax which is the the most modern and does the most to conceal -- but not eliminate :-( -- the async complexity...



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() } ];
}
}


Notice, instead of just grabbing the mongo _id from the user, we put away the whole mongo object. Unless this is a huge memory hog, we might as well have it hanging around so we can get any of the remotely stored properties.



Here's what the caller looks like...



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' } ];





share|improve this answer























  • Yes, but the problem is I need to implement sytax like that: value = fetchId('John'); so function fetchId should RETURN value (console.log is working properly, but return - not) ;)
    – Adam Jakś
    Nov 14 at 13:15












  • @AdamJakś - it can only return nothing or a promise to finish later. What it can't return is the result of findOne(), which hasn't run yet at the point fetchId returns. In the callback approach, it doesn't matter what the callback returns. The call back is called after findOne() runs.
    – danh
    Nov 14 at 15:45










  • Ok, thank You for the explicit explaining. But - what if I need to use this function in value of property in Object? Just like: { posts [ { content: 'lorem', creator_id: <fetchId function use> } ]. Do You think it is possible? How to give the creator_id key the user id value? ;)
    – Adam Jakś
    Nov 15 at 8:03










  • @AdamJakś - I understand what's troubling you. Please see the extensive amendment I made to the answer.
    – danh
    Nov 15 at 16:56












  • Thanks you a lot for great explaining. I implemented this code by adding a function to value property, just like: posts:[ { creator_id: fetchId('john'); } ] and in the function body I added code from your caller's code proposition: async fetchId(name) { let john = new MyMongoUser(name); await john.getReady(); john.mongoId(); } And the problem is now that console returns me an error: Post validation failed: creator_id: Cast to String failed for value "Promise { <pending> }" at path "creat or_id" In post schema I have creator_id set as string. Parse string is not a sollution.
    – Adam Jakś
    Nov 16 at 12:14


















0














A third way is a variation of suggestion #2 in @Karim's (perfectly good) answer. If the OP wants to code it as if results are being assigned from async code, an improvement would be to declare fetchId as async and await its result...



fetchId = async (name) => {
return User.findOne({name: name}).then(user => user.id);
};

let someId = await fetchId("John");
console.log(id)


edit



For any method on an object -- including a property getter -- that works asynchronously, the calling code needs to be aware and act accordingly.



This tends to spread upward in your system to anything that depends on caller's callers, and so on. We can't avoid this, and there's no syntactic fix (syntax is what the compiler sees). It's physics: things that take longer, just take longer. We can use syntax to partially conceal the complexity, but we're stuck with the extra complexity.



Applying this to your question, say we have an object representing a User which is stored remotely by mongo. The simplest approach is to think of the in-memory user object as unready until an async fetch (findOne) operation has completed.



Under this approach, the caller has just one extra thing to remember: tell the unready user to get ready before using it. The code below employs async/await style syntax which is the the most modern and does the most to conceal -- but not eliminate :-( -- the async complexity...



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() } ];
}
}


Notice, instead of just grabbing the mongo _id from the user, we put away the whole mongo object. Unless this is a huge memory hog, we might as well have it hanging around so we can get any of the remotely stored properties.



Here's what the caller looks like...



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' } ];





share|improve this answer























  • Yes, but the problem is I need to implement sytax like that: value = fetchId('John'); so function fetchId should RETURN value (console.log is working properly, but return - not) ;)
    – Adam Jakś
    Nov 14 at 13:15












  • @AdamJakś - it can only return nothing or a promise to finish later. What it can't return is the result of findOne(), which hasn't run yet at the point fetchId returns. In the callback approach, it doesn't matter what the callback returns. The call back is called after findOne() runs.
    – danh
    Nov 14 at 15:45










  • Ok, thank You for the explicit explaining. But - what if I need to use this function in value of property in Object? Just like: { posts [ { content: 'lorem', creator_id: <fetchId function use> } ]. Do You think it is possible? How to give the creator_id key the user id value? ;)
    – Adam Jakś
    Nov 15 at 8:03










  • @AdamJakś - I understand what's troubling you. Please see the extensive amendment I made to the answer.
    – danh
    Nov 15 at 16:56












  • Thanks you a lot for great explaining. I implemented this code by adding a function to value property, just like: posts:[ { creator_id: fetchId('john'); } ] and in the function body I added code from your caller's code proposition: async fetchId(name) { let john = new MyMongoUser(name); await john.getReady(); john.mongoId(); } And the problem is now that console returns me an error: Post validation failed: creator_id: Cast to String failed for value "Promise { <pending> }" at path "creat or_id" In post schema I have creator_id set as string. Parse string is not a sollution.
    – Adam Jakś
    Nov 16 at 12:14
















0












0








0






A third way is a variation of suggestion #2 in @Karim's (perfectly good) answer. If the OP wants to code it as if results are being assigned from async code, an improvement would be to declare fetchId as async and await its result...



fetchId = async (name) => {
return User.findOne({name: name}).then(user => user.id);
};

let someId = await fetchId("John");
console.log(id)


edit



For any method on an object -- including a property getter -- that works asynchronously, the calling code needs to be aware and act accordingly.



This tends to spread upward in your system to anything that depends on caller's callers, and so on. We can't avoid this, and there's no syntactic fix (syntax is what the compiler sees). It's physics: things that take longer, just take longer. We can use syntax to partially conceal the complexity, but we're stuck with the extra complexity.



Applying this to your question, say we have an object representing a User which is stored remotely by mongo. The simplest approach is to think of the in-memory user object as unready until an async fetch (findOne) operation has completed.



Under this approach, the caller has just one extra thing to remember: tell the unready user to get ready before using it. The code below employs async/await style syntax which is the the most modern and does the most to conceal -- but not eliminate :-( -- the async complexity...



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() } ];
}
}


Notice, instead of just grabbing the mongo _id from the user, we put away the whole mongo object. Unless this is a huge memory hog, we might as well have it hanging around so we can get any of the remotely stored properties.



Here's what the caller looks like...



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' } ];





share|improve this answer














A third way is a variation of suggestion #2 in @Karim's (perfectly good) answer. If the OP wants to code it as if results are being assigned from async code, an improvement would be to declare fetchId as async and await its result...



fetchId = async (name) => {
return User.findOne({name: name}).then(user => user.id);
};

let someId = await fetchId("John");
console.log(id)


edit



For any method on an object -- including a property getter -- that works asynchronously, the calling code needs to be aware and act accordingly.



This tends to spread upward in your system to anything that depends on caller's callers, and so on. We can't avoid this, and there's no syntactic fix (syntax is what the compiler sees). It's physics: things that take longer, just take longer. We can use syntax to partially conceal the complexity, but we're stuck with the extra complexity.



Applying this to your question, say we have an object representing a User which is stored remotely by mongo. The simplest approach is to think of the in-memory user object as unready until an async fetch (findOne) operation has completed.



Under this approach, the caller has just one extra thing to remember: tell the unready user to get ready before using it. The code below employs async/await style syntax which is the the most modern and does the most to conceal -- but not eliminate :-( -- the async complexity...



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() } ];
}
}


Notice, instead of just grabbing the mongo _id from the user, we put away the whole mongo object. Unless this is a huge memory hog, we might as well have it hanging around so we can get any of the remotely stored properties.



Here's what the caller looks like...



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' } ];






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 16 at 19:46

























answered Nov 13 at 20:31









danh

48.2k874113




48.2k874113












  • Yes, but the problem is I need to implement sytax like that: value = fetchId('John'); so function fetchId should RETURN value (console.log is working properly, but return - not) ;)
    – Adam Jakś
    Nov 14 at 13:15












  • @AdamJakś - it can only return nothing or a promise to finish later. What it can't return is the result of findOne(), which hasn't run yet at the point fetchId returns. In the callback approach, it doesn't matter what the callback returns. The call back is called after findOne() runs.
    – danh
    Nov 14 at 15:45










  • Ok, thank You for the explicit explaining. But - what if I need to use this function in value of property in Object? Just like: { posts [ { content: 'lorem', creator_id: <fetchId function use> } ]. Do You think it is possible? How to give the creator_id key the user id value? ;)
    – Adam Jakś
    Nov 15 at 8:03










  • @AdamJakś - I understand what's troubling you. Please see the extensive amendment I made to the answer.
    – danh
    Nov 15 at 16:56












  • Thanks you a lot for great explaining. I implemented this code by adding a function to value property, just like: posts:[ { creator_id: fetchId('john'); } ] and in the function body I added code from your caller's code proposition: async fetchId(name) { let john = new MyMongoUser(name); await john.getReady(); john.mongoId(); } And the problem is now that console returns me an error: Post validation failed: creator_id: Cast to String failed for value "Promise { <pending> }" at path "creat or_id" In post schema I have creator_id set as string. Parse string is not a sollution.
    – Adam Jakś
    Nov 16 at 12:14




















  • Yes, but the problem is I need to implement sytax like that: value = fetchId('John'); so function fetchId should RETURN value (console.log is working properly, but return - not) ;)
    – Adam Jakś
    Nov 14 at 13:15












  • @AdamJakś - it can only return nothing or a promise to finish later. What it can't return is the result of findOne(), which hasn't run yet at the point fetchId returns. In the callback approach, it doesn't matter what the callback returns. The call back is called after findOne() runs.
    – danh
    Nov 14 at 15:45










  • Ok, thank You for the explicit explaining. But - what if I need to use this function in value of property in Object? Just like: { posts [ { content: 'lorem', creator_id: <fetchId function use> } ]. Do You think it is possible? How to give the creator_id key the user id value? ;)
    – Adam Jakś
    Nov 15 at 8:03










  • @AdamJakś - I understand what's troubling you. Please see the extensive amendment I made to the answer.
    – danh
    Nov 15 at 16:56












  • Thanks you a lot for great explaining. I implemented this code by adding a function to value property, just like: posts:[ { creator_id: fetchId('john'); } ] and in the function body I added code from your caller's code proposition: async fetchId(name) { let john = new MyMongoUser(name); await john.getReady(); john.mongoId(); } And the problem is now that console returns me an error: Post validation failed: creator_id: Cast to String failed for value "Promise { <pending> }" at path "creat or_id" In post schema I have creator_id set as string. Parse string is not a sollution.
    – Adam Jakś
    Nov 16 at 12:14


















Yes, but the problem is I need to implement sytax like that: value = fetchId('John'); so function fetchId should RETURN value (console.log is working properly, but return - not) ;)
– Adam Jakś
Nov 14 at 13:15






Yes, but the problem is I need to implement sytax like that: value = fetchId('John'); so function fetchId should RETURN value (console.log is working properly, but return - not) ;)
– Adam Jakś
Nov 14 at 13:15














@AdamJakś - it can only return nothing or a promise to finish later. What it can't return is the result of findOne(), which hasn't run yet at the point fetchId returns. In the callback approach, it doesn't matter what the callback returns. The call back is called after findOne() runs.
– danh
Nov 14 at 15:45




@AdamJakś - it can only return nothing or a promise to finish later. What it can't return is the result of findOne(), which hasn't run yet at the point fetchId returns. In the callback approach, it doesn't matter what the callback returns. The call back is called after findOne() runs.
– danh
Nov 14 at 15:45












Ok, thank You for the explicit explaining. But - what if I need to use this function in value of property in Object? Just like: { posts [ { content: 'lorem', creator_id: <fetchId function use> } ]. Do You think it is possible? How to give the creator_id key the user id value? ;)
– Adam Jakś
Nov 15 at 8:03




Ok, thank You for the explicit explaining. But - what if I need to use this function in value of property in Object? Just like: { posts [ { content: 'lorem', creator_id: <fetchId function use> } ]. Do You think it is possible? How to give the creator_id key the user id value? ;)
– Adam Jakś
Nov 15 at 8:03












@AdamJakś - I understand what's troubling you. Please see the extensive amendment I made to the answer.
– danh
Nov 15 at 16:56






@AdamJakś - I understand what's troubling you. Please see the extensive amendment I made to the answer.
– danh
Nov 15 at 16:56














Thanks you a lot for great explaining. I implemented this code by adding a function to value property, just like: posts:[ { creator_id: fetchId('john'); } ] and in the function body I added code from your caller's code proposition: async fetchId(name) { let john = new MyMongoUser(name); await john.getReady(); john.mongoId(); } And the problem is now that console returns me an error: Post validation failed: creator_id: Cast to String failed for value "Promise { <pending> }" at path "creat or_id" In post schema I have creator_id set as string. Parse string is not a sollution.
– Adam Jakś
Nov 16 at 12:14






Thanks you a lot for great explaining. I implemented this code by adding a function to value property, just like: posts:[ { creator_id: fetchId('john'); } ] and in the function body I added code from your caller's code proposition: async fetchId(name) { let john = new MyMongoUser(name); await john.getReady(); john.mongoId(); } And the problem is now that console returns me an error: Post validation failed: creator_id: Cast to String failed for value "Promise { <pending> }" at path "creat or_id" In post schema I have creator_id set as string. Parse string is not a sollution.
– Adam Jakś
Nov 16 at 12:14





Popular posts from this blog

鏡平學校

ꓛꓣだゔៀៅຸ໢ທຮ໕໒ ,ໂ'໥໓າ໼ឨឲ៵៭ៈゎゔit''䖳𥁄卿' ☨₤₨こゎもょの;ꜹꟚꞖꞵꟅꞛေၦေɯ,ɨɡ𛃵𛁹ޝ޳ޠ޾,ޤޒޯ޾𫝒𫠁သ𛅤チョ'サノބޘދ𛁐ᶿᶇᶀᶋᶠ㨑㽹⻮ꧬ꧹؍۩وَؠ㇕㇃㇪ ㇦㇋㇋ṜẰᵡᴠ 軌ᵕ搜۳ٰޗޮ޷ސޯ𫖾𫅀ल, ꙭ꙰ꚅꙁꚊꞻꝔ꟠Ꝭㄤﺟޱސꧨꧼ꧴ꧯꧽ꧲ꧯ'⽹⽭⾁⿞⼳⽋២៩ញណើꩯꩤ꩸ꩮᶻᶺᶧᶂ𫳲𫪭𬸄𫵰𬖩𬫣𬊉ၲ𛅬㕦䬺𫝌𫝼,,𫟖𫞽ហៅ஫㆔ాఆఅꙒꚞꙍ,Ꙟ꙱エ ,ポテ,フࢰࢯ𫟠𫞶 𫝤𫟠ﺕﹱﻜﻣ𪵕𪭸𪻆𪾩𫔷ġ,ŧآꞪ꟥,ꞔꝻ♚☹⛵𛀌ꬷꭞȄƁƪƬșƦǙǗdžƝǯǧⱦⱰꓕꓢႋ神 ဴ၀க௭எ௫ឫោ ' េㇷㇴㇼ神ㇸㇲㇽㇴㇼㇻㇸ'ㇸㇿㇸㇹㇰㆣꓚꓤ₡₧ ㄨㄟ㄂ㄖㄎ໗ツڒذ₶।ऩछएोञयूटक़कयँृी,冬'𛅢𛅥ㇱㇵㇶ𥄥𦒽𠣧𠊓𧢖𥞘𩔋цѰㄠſtʯʭɿʆʗʍʩɷɛ,əʏダヵㄐㄘR{gỚṖḺờṠṫảḙḭᴮᵏᴘᵀᵷᵕᴜᴏᵾq﮲ﲿﴽﭙ軌ﰬﶚﶧ﫲Ҝжюїкӈㇴffצּ﬘﭅﬈軌'ffistfflſtffतभफɳɰʊɲʎ𛁱𛁖𛁮𛀉 𛂯𛀞నఋŀŲ 𫟲𫠖𫞺ຆຆ ໹້໕໗ๆทԊꧢꧠ꧰ꓱ⿝⼑ŎḬẃẖỐẅ ,ờỰỈỗﮊDžȩꭏꭎꬻ꭮ꬿꭖꭥꭅ㇭神 ⾈ꓵꓑ⺄㄄ㄪㄙㄅㄇstA۵䞽ॶ𫞑𫝄㇉㇇゜軌𩜛𩳠Jﻺ‚Üမ႕ႌႊၐၸဓၞၞၡ៸wyvtᶎᶪᶹစဎ꣡꣰꣢꣤ٗ؋لㇳㇾㇻㇱ㆐㆔,,㆟Ⱶヤマފ޼ޝަݿݞݠݷݐ',ݘ,ݪݙݵ𬝉𬜁𫝨𫞘くせぉて¼óû×ó£…𛅑הㄙくԗԀ5606神45,神796'𪤻𫞧ꓐ㄁ㄘɥɺꓵꓲ3''7034׉ⱦⱠˆ“𫝋ȍ,ꩲ軌꩷ꩶꩧꩫఞ۔فڱێظペサ神ナᴦᵑ47 9238їﻂ䐊䔉㠸﬎ffiﬣ,לּᴷᴦᵛᵽ,ᴨᵤ ᵸᵥᴗᵈꚏꚉꚟ⻆rtǟƴ𬎎

Why https connections are so slow when debugging (stepping over) in Java?