简体   繁体   中英

Using Bluebird Promises in Node.JS with 2 async operations

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.");
  });
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM