You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm not sure why you would reference both, since the .exec() is just more code with no benefit. Or am I missing something?
I found out by means of a colleague who unknowingly wrote this since the docs suggested it. As far as I can tell .exec() is only useful for invoking a callback-style response.
@moeriki The difference is that the return type of Model.findOne is a Query. They just happen to have added a then to it so it is "thennable" but it is not a true promise. The return from exec is actually a promise if you don't supply a callback to the exec. While you might not care about this distinction some of us do.
Reacted by Dieter Luypaert, Maksym Minenko and Joseph Cobbinah Ofori
I take back my words. Since users may have certain expectations from Promises I'd keep the .exec() as the most prominent documentation. We could still mention the "thennable" object in smaller print.
You're right that queries are not promises: https://mongoosejs.com/docs/queries.html#queries-are-not-promises . The most meaningful difference is that if you await on the same query object twice, you will execute the query twice, whereas await on the same promise twice only executes the query once. We did also run into an issue where node's async_hooks don't work properly if you await on a custom thennable, but that's a node issue that mongoose can't work around.
TLDR; there are reasons to prefer using exec(), but for most apps it doesn't matter which one.
@jloveridge I'm curious to hear why you prefer a true promise over a thennable. Is it one of the reasons I listed or something else?
It works but is it faulty? I do the same for updating, saving and deleting documents
Or is it that i should do mongoose.Promose = require('bluebird') to make this "work" as intended
@Enado95 I'm not sure what you mean by 'work'. The code as written definitely needs some work - its clumsy and suppresses errors. Why do you do .then(data => data)? That does nothing besides create an unnecessary promise. Also, why the .catch()? That means that you ignore all errors.
@Enado95 I'm not sure what you mean by 'work'. The code as written definitely needs some work - its clumsy and suppresses errors. Why do you do .then(data => data)? That does nothing besides create an unnecessary promise. Also, why the .catch()? That means that you ignore all errors.
@vkarpov15 When say it works. I mean it returns a response and if there's mongo error it returns the a 500 response as well; here's my exact implementation below for deleting a record. I do the same for updating and save():
exports.deleteCompany=async(req,res)=>{constcompany=awaitCompany.findByIdAndDelete(mongoose.Types.ObjectId(req.params.id)).then(data=>{if(!data)returnres.status(404).send('Company with the given id was not found')res.send('Company successfully deleted')}).catch(err=>{returnres.status(500).send({message: err.message})})}
Since the .then(data => data) does nothing, how would truly make this method async and catch errors?
On Sun, Sep 29, 2019 at 6:53 PM Valeri Karpov ***@***.***> wrote:
find() and findOneAndUpdate() both return mongoose queries, so they should
be fine as far as await is concerned. The exec() isn't necessary.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#8110?email_source=notifications&email_token=AGE5KHRAVXA4RD5QBJSNAZ3QME5WHA5CNFSM4IR7P3PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD74BVYI#issuecomment-536353505>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AGE5KHUKXKAOX3NTH2YK67DQME5WHANCNFSM4IR7P3PA>
.
It works but is it faulty? I do the same for updating, saving and deleting documents
Or is it that i should do mongoose.Promose = require('bluebird') to make this "work" as intended
A string is not an error. I would avoid throwing strings by any means necessary. Just remove the entire catch. Let your calls to async(companyID) handle the error how they see fit. For instance, they may prefer to use the error.code 11000 or duplicate key error to change the error response to the user.
Activity
vkarpov15 commentedon Sep 4, 2019
Both approaches work. We'll add a note to the docs.
moeriki commentedon Sep 5, 2019
I'm not sure why you would reference both, since the
.exec()is just more code with no benefit. Or am I missing something?I found out by means of a colleague who unknowingly wrote this since the docs suggested it. As far as I can tell
.exec()is only useful for invoking a callback-style response.I could PR docs.
jloveridge commentedon Sep 6, 2019
@moeriki The difference is that the return type of
Model.findOneis aQuery. They just happen to have added athento it so it is "thennable" but it is not a true promise. The return fromexecis actually a promise if you don't supply a callback to theexec. While you might not care about this distinction some of us do.moeriki commentedon Sep 6, 2019
I see. Thanks for the feedback.
I take back my words. Since users may have certain expectations from Promises I'd keep the
.exec()as the most prominent documentation. We could still mention the "thennable" object in smaller print.vkarpov15 commentedon Sep 10, 2019
You're right that queries are not promises: https://mongoosejs.com/docs/queries.html#queries-are-not-promises . The most meaningful difference is that if you
awaiton the same query object twice, you will execute the query twice, whereasawaiton the same promise twice only executes the query once. We did also run into an issue where node's async_hooks don't work properly if youawaiton a custom thennable, but that's a node issue that mongoose can't work around.TLDR; there are reasons to prefer using
exec(), but for most apps it doesn't matter which one.@jloveridge I'm curious to hear why you prefer a true promise over a thennable. Is it one of the reasons I listed or something else?
Enado95 commentedon Sep 14, 2019
So @vkarpov15 i use this approach :
async(companyID) => { await User.find({company:companyID}).then(data =>{ return data }).catch(err => { return err.message }) }It works but is it faulty? I do the same for updating, saving and deleting documents
Or is it that i should do mongoose.Promose = require('bluebird') to make this "work" as intended
vkarpov15 commentedon Sep 19, 2019
@Enado95 I'm not sure what you mean by 'work'. The code as written definitely needs some work - its clumsy and suppresses errors. Why do you do
.then(data => data)? That does nothing besides create an unnecessary promise. Also, why the.catch()? That means that you ignore all errors.Enado95 commentedon Sep 19, 2019
@vkarpov15 When say it works. I mean it returns a response and if there's mongo error it returns the a 500 response as well; here's my exact implementation below for deleting a record. I do the same for updating and save():
Since the
.then(data => data)does nothing, how would truly make this method async and catch errors?vkarpov15 commentedon Sep 23, 2019
This implementation for deleting a company should work fine. Not sure what you mean by "truly make this method async".
Enado95 commentedon Sep 24, 2019
So the same implementation for find or findOneAndUpdate would work similarly?
Also, since its an async function, is the
.exec()required?vkarpov15 commentedon Sep 29, 2019
find() and findOneAndUpdate() both return mongoose queries, so they should be fine as far as
awaitis concerned. Theexec()isn't necessary.However, it is typically better to use
exec()because of better stack trace support.Enado95 commentedon Sep 29, 2019
DevBrent commentedon Sep 2, 2020
A string is not an error. I would avoid throwing strings by any means necessary. Just remove the entire catch. Let your calls to
async(companyID)handle the error how they see fit. For instance, they may prefer to use the error.code11000or duplicate key error to change the error response to the user.https://web.archive.org/web/20111226063046/http://www.devthought.com/2011/12/22/a-string-is-not-an-error/