9

Utilizing Bluebird to Promisfy Mongoose, I have a Promise.map(function with a series of if/else for looping through an array to see if a reference doc exists, else create one..

Assigning the product of findOneAsync to a variable, to then assign 'variable._id' to a new doc in the making (the main promise), the console logs {"isFulfilled":false,"isRejected":false}

Here's a snippet:

for (i=0; i<items.length; i++) {
    var existingItem = Models.Items.findOneAsync({ item: items[i] });
    console.log( "existingItem : ");
    console.log( JSON.stringify(existingItem) );
    console.log( "existingItem._id : " + existingItem._id );

Here's a log:

existingItem : 
{"isFulfilled":false,"isRejected":false}
existingItem._id : undefined

Why might the existingItem variable be pending for the Model.Item.findOneAsync..?

Stacks
  • 369
  • 3
  • 6
  • 19
  • I don't see you assigning a value to `variable._id`. Are we supposed to imagine what your code looks like? – JLRishe Feb 12 '15 at 06:03

5 Answers5

9

Your question is not really clear, but my question to you would be: why would existingItem not be pending right after you retrieved it?

Do you understand how to use promises? Most of the time you need to get at their resolved values using .then() or other promise manipulation functions:

var existingItem = Models.Items.findOneAsync({ item: items[i] });
existingItem.then(function (value) {
    console.log( "existingItem : ");
    console.log( JSON.stringify(existingItem) );
    console.log( JSON.stringify(value); );
    console.log( "existingItem._id : " + existingItem._id );
});
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • Appreciate the pointer. Here's where this stands: https://stackoverflow.com/questions/28482021/promise-map-not-finshing-because-subsequent-promise-join-finishes-first-promise – Stacks Feb 12 '15 at 16:08
1

You need to wait until the promise gets resolved (or rejected). You can use any one of the following two ways:

1. By 'awaiting' to get the final state of the promise as follows:

var existingItem = await Models.Items.findOneAsync({ item: items[i] });

2. By handling the promise using '.then' handler as follows:

return Models.Items.findOneAsync({ item: items[i] })
    .then(function(existingItem) {
        console.log("existingItem", existingItem);
zlatanned
  • 99
  • 1
  • 4
0

I think you want:

return Promise.each(items, function(item) {
  return Models.Items.findOneAsync({item: item}).then(function(existingItem) {
    console.log("existingItem", existingItem);
  });
});
Esailija
  • 138,174
  • 23
  • 272
  • 326
  • Is there a better pattern than this: https://stackoverflow.com/questions/28482021/promise-map-not-finshing-because-subsequent-promise-join-finishes-first-promise – Stacks Feb 12 '15 at 16:09
0

findOneAsync() simply hasn't finished running yet when you start writing the console.logs.

Also complicating things, it looks like findOneAsync() is returning a Promise (status is neither fulfilled nor rejected yet at the point you are writing logs).

So if you want to store and log the found item, you need to

  1. Wait for the Promise to resolve by using its .then() fucntion, and
  2. Retrieve the found item from the "resolved value". findOneAsync() should pass the found item object as a parameter to its resolve() function (i.e. somewhere inside findOneAsync() there would be: resolve(foundItem);).

Assuming all that, this should work:

    for (i=0; i<items.length; i++) {
        var findPromise = Models.Items.findOneAsync({ item: items[i] });
        //the next line won't run until findOneAsync finishes
        findPromise.then(resolveResult => {
            var existingItem = resolveResult;
            console.log( "existingItem : ");
            console.log( JSON.stringify(existingItem) );
            console.log( "existingItem._id : " + existingItem._id );
        }
    }
archie
  • 1
  • 2
0

The root cause is, your are not waiting until the operation is finished. You are logging before findOne operation is finished.

You can use either then or await to wait until the operation finishes.

  • then

    Item.findOne({ where: { id: your_id } })
        .then(result => console.log(result))
    
  • await function must be prefixed with async key, but this code is much cleaner

    const result = await Item.findOne({ where: { id: your_id  } })
    console.log(result)
    
Saahithyan Vigneswaran
  • 6,841
  • 3
  • 35
  • 45