-1

I am working on a small shopping site using nodejs and mongodb. I have been able to store and retrieve data from my database. However, I can't get this particular function to work which is supposed to retrieve products from user cart. The products are retrieved into the then() block, but when i try to return or print the products by performing some operations in the products, i get output as Promise { pending }.

Before marking this question as duplicate(which it is not, but if you think it is), atleast help me with solve this.

const productIds = this.cart.items.map(eachItem => {
    return eachItem.pid;
});  //to get product IDs of all the products from the cart
const cartData = db.collection('products') //db is the database function and works fine
    .find({_id: {$in: productIds}})
    .toArray()
    .then(products => {
        console.log(products); //all the products are printed correctly
        products.map(eachProduct => { 
            return {
                ...eachProduct,
                quantity: this.cart.items.find(eachCP => {
                    return eachCP.pid.toString() === eachProduct._id.toString()                            
                }).quantity //to get the quantity of that specific product (here eachProduct)
            };
        })
    })
    .catch(err => {
        console.log(err);
    });
console.log('cartData: ', cartData); //but here it prints Promise /{ pending /}

I can't understand why i get Promise { } as output although i get the data from the database successfully in the then() block. Sorry for the messsy code btw. I'm new to mongodb and don't have so much knowledge about promises too.

NameError
  • 17
  • 4
  • Your `console.log('cartData: ', cartData);` is running BEFORE the promise resolves and before the `.then()` handler is called. Promises don't block. `.then()` doesn't block. They just register callbacks that will get called sometime in the future and then the next line of your code (your `console.log()`) executes long before the `.then()` handler is called. – jfriend00 Aug 19 '19 at 03:06
  • hey @jfriend00 thanks i understood what u said. But instead of printing i returned the cartData and tried to retrieve the data in another function, i still can't get the data it says **undefined**, i don't get it. – NameError Aug 19 '19 at 06:36

1 Answers1

1

Promise#then does not "wait" in the sense that the next statement in the program would be delayed until the promise completes.

It "waits" only in the sense that execution of the callback that you pass to then is delayed until the promise completes.

But your current function (the one that set up the then) does not block and continues to run immediately. Meaning that everything outside of the function you pass to then may see the promise in its still incompleted state.

You probably want to make use of the async/await construct, as described (for example) in the linked duplicate thread.

Thilo
  • 241,635
  • 91
  • 474
  • 626
  • *Will* see the promise in its pending state, in fact; the callbacks won't be called until the current event loop is completed. – jonrsharpe Aug 18 '19 at 09:06
  • @jonrsharpe. True. But the promise could already have been completed at the top of the function or by other non-asynchronous code in between (of course not the case here). – Thilo Aug 18 '19 at 09:10
  • And yes, the callbacks won't be called until the next event loop, even if the promise happened to be already completed. So the code below will always run before the callbacks, no matter what. – Thilo Aug 18 '19 at 09:17
  • yes, that's true; the promise may be resolved, but the callback still won't have been invoked. – jonrsharpe Aug 18 '19 at 09:35
  • @Thilo I still don't get it, since i got all the data in the then() block, doesn't that mean i can just work with it in that block accordingly, what is stopping it, Also i already tried wrapping the whole code in an async function and return the result, it still won't work. Can you help me by posting the code? – NameError Aug 18 '19 at 09:48
  • 1
    Yes, you can work with the result of the promise in the `then` block. But the `console.log('cartData: ', cartData)` is outside of that block. Move it inside and it will print correctly. – Thilo Aug 18 '19 at 10:09
  • 1
    @testid123 remember that the return value of a `then()` invocation is not the return value of the callback. It's a new promise for the result of the callback, as the callback hasn't been run yet. – Bergi Aug 18 '19 at 20:54
  • @Thilo thanks, now i get it why it wouldn't print the data as i expected. But if i return the data instead of printing and try to call it from another function like this: `User.getCartData().then(cartData => { console.log('cartData: ', cartData)}).catch(err => console.log(err));` , this should print right?, why am i still getting output as **undefined**. What am i doing wrong? – NameError Aug 19 '19 at 06:47
  • You may be missing `return` statements in your callback. Without a `return` at the end of a function, it just return `undefined`. In your code above, you probably need to say `return products.map(...)` instead of just `products.map(...)`. – Thilo Aug 19 '19 at 08:14