Quy Quy - 1 month ago 8
Node.js Question

Mongoose inside a promise change happens late

I am writing an API in NodeJS in which I use Mongoose and BlueBird. Regarding promise chain, my data was supposed to go through waterfall functions but it didn't. Let my example start with

getTagNames
to get some
JSON
, feeding data to
retrieveTag
to query and end up with
res.json()
.

exports.getTagValues = function (req, res) {
var userId = req.params.uid;
getTagNames(req, res)
.then(retrieveTag)
.then(function (data) {
console.log('tags', data);
res.json(200, data);
})
.catch(function(err){
console.log('err', err);
//handle Error
})
}


Here is my toy data,

function getTagNames(req, res) {
var userId = req.params.uid;
return new Promise.resolve({
'userId': userId,
'variables': [
{ id: 1, name: 'hotel', type: 'String' },
{ id: 2, name: 'location', type: 'String' }
],
})
}


The way I query data. After querying inside mongo, I check whether or not have a document with
userID
. In case not, insert and return document. Note
Tag
is my mongo model

function retrieveTag(data){
Tag.findOne({'userId': data.userId})
.exec()
.then( function(tag){
if (tag) {
console.log('result', tag);
// do something ...
return tag;
}
else {
var newTag = new Tag({
advertiserId: advertiserId,
variables: variables
});
newTag.save()
.then(function () {
console.log('newTag', newTag);
return newTag;
});
}
})
}


Here is my result (
userId
is
1
), my expectation is
console.log('tags', data);
occurs after all then
data
should not be
undefined


tags undefined
GET /api/tag/values/1 200 3ms
newTag { __v: 0,
userId: '1',
_id: 581b96090e5916cf3f5112fe,
variables:
[ { type: 'String', name: 'hotel', id: 1 },
{ type: 'String', name: 'location', id: 2 } ] }


My question is how can I fix it. If there's some unclear, please help me correct.

Answer

The explanation is a bit unclear, but if I follow you right you loose data in the promise resolvement chain.

When reading your code, I notice that retrieveTag does not return the Mongoose promise. To let .then in getTagValues use the data found in retrieveTag.

So change to this:

function retrieveTag(data){
  return Tag.findOne({'userId': data.userId})
    .exec()
    .then( function(tag){
      ...
    })
}
Comments