1

I have a scenario where I need to get the records from MySQL database and update in redis cache and close the MySQL and redis connection.

Steps:

  1. Open MySQL connection
  2. Get records from MySQL database on success
  3. Update Redis cache on success from MySQL Query Result
  4. Close the MySQL db connection.

I am trying to do using Bluebird promises but not getting appropriate results.

Problem in below code is done is getting called initially and even in processBreakingNewsData function which supposed to be executed last.

Please correct me in the places where I have done mistake

Below is my node.js code

constants.js file

var Promise = require('bluebird');

module.exports = {
  getRedisConnection: function () {
    return require("redis").createClient(6379, 'XXXX', { auth_pass: 'XXXX' });
  },
  getMySqlConnection: function () {
    var conObj = { host: "localhost", user: "root", password: "", database: "deccan" };

    var connection = require("mysql").createConnection(conObj);

    return new Promise(function (resolve, reject) {
      connection.connect(function (error) { 
        if (error)
          reject(error);
        else
          resolve(connection);
      });
    });       
  }
};

testing.js file

var constants = require("./constants.js");
var Promise = require('bluebird');

constants.getMySqlConnection().then(processBreakingNewsData)
.catch(function (e) {
  console.log("Error : " + e);
}).done(function () {
  console.log("Finished");
});

function processBreakingNewsData(connection) {
  return new Promise(function (resolve, reject) {
    connection.query("select id, text, DATE_FORMAT(created_at, '%Y-%m-%d %H:%i:%s') as 'created_at' from breakingnews;", function (error, results) {
      connection.end();

      if (error)
        reject(error);
      else
        resolve(results);
    });

  }).then(function (results) {
    return new Promise(function (resolve, reject) {
      var value = "";

      if (results.length > 0)
        value = JSON.stringify(results);

      var client = constants.getRedisConnection();

      client.set("bnews", value, function (err, reply) {
        if (err)
          reject(new Error("Error during Update of BreakingNews : " + err));
        else
          resolve(reply);
      });
    });           
  }).catch(function (e) {
    console.log("Error during Update of BreakingNews : " + e);

  }).done(function (result) {
    console.log("Breaking News Updated in Redis.");
  });
}

1 Answer 1

1

2 issues here :

  1. then always return a promise

.then always returns a promise. If you don't return one yourself, a resolved promise is created with the return value. That's what happens here : the .then in processBreakingNewsData immediatly returns a resolved promise, which then executes your done callback.

To avoid this, you need to explicitly return an ongoing promise :

function processBreakingNewsData(connection)
{
    return new Promise(function (resolve, reject) 
    {
        // ...
    }).then(function (results) 
    {
        return new Promise(function (resolve, reject) {
            // ...
  1. done does not return a promise

Your last done handler does not return a promise, which means the entire processBreakingNewsData does not return a promise. So, again, the calling then returns immediately with a resolved promise.

Never use done. This is from the documentation :

.done(
    [function(any value) fulfilledHandler],
    [function(any error) rejectedHandler]
) -> undefined 

The use of this method is heavily discouraged and it only exists for historical reasons.

You can safely replace done by then here, since you catch errors beforehand.

Sign up to request clarification or add additional context in comments.

4 Comments

how can I handle the first 'then' -> constants.getMySqlConnection().then(processBreakingNewsData)
@Sharath I don't see an issue here, you pass a function returning a promise so it should be ok. What unexpected behavior do you encounter ?
I have updated the source code with the changes you mentioned. Now the result is done block is executed initially itself and then Breaking News Updated in Redis. is printed. But actually Finished should have been last statement to be executed. I mean should I put the processBreakingNewsData function inside a promise ?
@Sharath there is an issue with the done function in bluebird : it doesn't return a promise like then. Usage of done is discouraged. I have updated my answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.