How to resolve: Promise { } – nodejs error

A promise if not resolved will remain on the pending state and at such any attempt to accessed it returned value will result in the error: Promise { <pending>}. A promise is used for asynchronous computation and needs to be resolved by calling the .then to receive the value returned by the promise or by calling await if using async/await instead.

Promise

The following nodejs code inserts a newly registered user email and password into the users table, but must first of all encrypt the password using bcrypt.hash function.

app.post("/api/v1/dev/signup", (req, res) => {
    bcrypt.hash(req.body.password, 10).then((hash) => {
        const query = 'INSERT INTO users (email, password) VALUES ?';
        const values = [
            [req.body.email, hash]
        ]
        ConnectDB.query(query, [values] , function(err, results) {
        if (err){
            //log error here
            return res.json( { "msg" : "An error occurred during signup process. Please try again" } );
        }
        return res.json( { "msg" : "user\'s record is successfully saved in database" } )
        });
    })
})

bcrypt.hash() is a promise and has to be resolved with the .then keyword to avoid the error message: Promise { <pending> }

bcrypt.hash(req.body.password, 10).then(() => {
    ...
})

The issue – Promise without .then

Now look at this other scenario

app.post("/api/v1/dev/signup", (req, res) => {
    const promisedHash = bcrypt.hash(req.body.password, 10).then((hash) => {
        console.log(`hash value is ${hash}`)
        return hash
    })
    console.log(promisedHash)
    const query = 'INSERT INTO users (email, password) VALUES ?';
    const values = [
        [req.body.email, promisedHash]
    ]
    ConnectDB.query(query, [values] , function(err, results) {
      if (err){
          //log error here
          return res.json( { "msg" : "An error occurred during signup process. Please try again" } );
      }
      return res.json( { "msg" : "user\'s record is successfully saved in database" } )
    });
})

We call the bcrypt.hash function (which is an asynchronous function) and assign the its return value to the variable: promisedHash. Some things to observe here:

  1. bcrypt.hash function is truly an asynchronous function as revealed in the order the console.log values printed
  2. The call to process to hash the password started when bcrypt.hash function was called but while the asynchronous function had not finished with what it was doing, execution moved to console.log(promisedHash) hence the value: Promise { <pending> }
  3. If you have a need to first assign the returned value of a promise to a value (like in my case: promisedHash), make sure to still use the .then keyword to get the returned value otherwise just go with what i did in the first sample code above by using the returned value in the .then section.
bcrypt.hash(...what i want to hash here...).then((returnedhashfrombcrypt) => {
    ...I use my bcrypt value inside this function instead of assigning the value   of bcrypt.hash to another variable
})

Please remember, if you must assign the value of the promise to a variable and expect to use that variable, you must still use the .then keyword to be able to access the returned value of the promise. See code below,

app.post("/api/v1/dev/signup", (req, res) => {
    const promisedHash = bcrypt.hash(req.body.password, 10).then((hash) => {
        console.log(`hash value is ${hash}`)
        return hash
    })
    //console.log(promisedHash)
    promisedHash.then((samehash) => {
        //i can then use the hash value that the promise returned
        //see how i used it in the code that follows
        console.log(`same hash like before ${samehash}`)
        const query = 'INSERT INTO users (email, password) VALUES ?';
        const values = [
            [req.body.email, samehash]
        ]
        ConnectDB.query(query, [values] , function(err, results) {
        if (err){
            //log error here
            return res.json( { "msg" : "An error occurred during signup process. Please try again" } );
        }
        return res.json( { "msg" : "user\'s record is successfully saved in database" } )
        });
    })
})

Again notice that this time because we use the .then keyword while accessing the promise returned value from the variable: promisedHash, the console.log prints its message in the right order.

Async/Await

My preferred way to resolving promises is using the async/await method. Look at the code below and see how simple it looks with async/await:

app.post("/api/v1/dev/signup", async (req, res) => {
    const promisedHash = await bcrypt.hash(req.body.password, 10)
    console.log(promisedHash)
    const query = 'INSERT INTO users (email, password) VALUES ?';
    const values = [
        [req.body.email, promisedHash]
    ]
    ConnectDB.query(query, [values] , function(err, results) {
    if (err){
        //log error here
        return res.json( { "msg" : "An error occurred during signup process. Please try again" } );
    }
    return res.json( { "msg" : "user\'s record is successfully saved in database" } )
    });
})

There is nothing wrong with this code; promisedHash prints its value this time as can be seen in the terminal (see below marker); we simply marked the beginning of the function with async and the beginning of the promise that is to be resolved (in this case the bcrypt function) with await.

Another issue – Async without Await

You will experience the same error: Promise { <pending> } if after you have marked a function as an async function, you forget to mark the beginning of each promise within the function with the await keyword. See example code below:

app.post("/api/v1/dev/signup", async (req, res) => {
    const promisedHash = bcrypt.hash(req.body.password, 10)
    console.log(promisedHash)
    const query = 'INSERT INTO users (email, password) VALUES ?';
    const values = [
        [req.body.email, promisedHash]
    ]
    ConnectDB.query(query, [values] , function(err, results) {
    if (err){
        //log error here
        return res.json( { "msg" : "An error occurred during signup process. Please try again" } );
    }
    return res.json( { "msg" : "user\'s record is successfully saved in database" } )
    });
})
Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

You May Also Like