0

I am trying write a cron function in nodejs which fetches user_ids of all the users from the db and then I want to parse through each user_id.

Here is my code :

cron.schedule('43 11 * * *', function(){
  var now = moment()
  var formatted = now.format('YYYY-MM-DD HH:mm:ss')
  console.log('Starting the cron boss!');
  var dbSelectPromise = function(db, sql1) {
      return new Promise(function(resolve, reject) {
          db.select(sql1, function(err, data) {
              if (err) {
                  reject(err)
              } else {
                  resolve(data)
              }
          })
      })
    }
    var users =[]
    var sql = "select distinct(user_id) from user_level_task"
    dbSelectPromise(db,sql).then(function(secondResult){
      for(i=0;i<secondResult.length;i++){
      var sql1 = "select max(level_id) as level from user_level_task where user_id ="+secondResult[i].user_id
      dbSelectPromise(db,sql1).then(function(thirdResult){
        console.log(thirdResult)
        console.log(current)
        var sql2 = "select task_id form user_level_task where user_id = '"+secondResult[i].user_id+"' and level_id = '"+thirdResult[0].level+"' "
        dbSelectPromise(db,sql2).then(function(fourthResult){
          var leng = fourthResult.length
          for(i=0;i<leng;i++){
            console.log(fourthResult[i])
          }
        })
      })
     }
    })
});

The problem i am facing is i cannot access value of i in third and fourth promises. Please help!

2 Answers2

0

I think what's happening is that i is no longer the same when you create those new promises because the for loop is still running. It appears that what you really need is the user_id and level_id. I suggest you restructure your code a bit to reduce nesting and pass on the values you need for future promises.

Perhaps something similar to this:

dbSelectPromise(db, sql)
.then(secondResult => {
  const levelPromises = [];
  secondResult.forEach(res => {
    levelPromises.push(getLevelByUserId(res.user_id, db));
  });      
  return Promise.all(levelPromises); // Promise.all only if you want to handle all success cases
})
.then(result => {
  result.forEach( level => {
    { userId, queryResult } = level;
    // ...
  })
  //...
})
.catch(err => {
  console.log(err);
});

function getLevelByUserId(userId, db) {
  const query = `select max(level_id) as level from user_level_task where user_id = ${userId}`;
  return dbselectPromise(db, query).then(result => { userId, result });
}

It creates an array of all the get level queries as promises and then passes it along to the next step using Promise.all() which will only resolve if all queries were successful. At that point, you will have access to the userId again of each result because we returned it in our new function for your next set of queries.

I think you should abstract your queries a bit further instead of using a generic dbSelectPromise and don't forget to catch() at the end otherwise you won't know what's happening.

Note: It assumes your db variable instantiated properly and your original db.select doesn't need to be returned based on whatever library you're using. There's also some new syntax there.

Tony
  • 186
  • 1
  • 4
0

The problem i am facing is i cannot access value of i in third and fourth promises. Please help!

This is because you're using reinitializing i without using let. When the loop is in process, the value will be different than what you expect.

each promise is dependant on the other and need to run synchronously

For this to work, You need to chain promises. Also, you can make use of Promise.all() to execute a bunches of promises at once. Remember, Promise.all() is all or nothing.

Making those changes to your code, I get the following structure.

'use strict';

let _ = require('lodash');

function dbSelectPromise(db, sql1) {
  return new Promise((resolve, reject) => {
    return db.select(sql1, (err, data) => {
      if (err) {
        return reject(err);
      }
      return resolve(data);
    });
  });
}

function process(secondResult) {
  let sql1 = "select max(level_id) as level from user_level_task where user_id =" + secondResult[i].user_id;
  return dbSelectPromise(db, sql1).then(function (thirdResult) {
    console.log(thirdResult);
    let sql2 = "select task_id form user_level_task where user_id = '" + secondResult[i].user_id + "' and level_id = '" + thirdResult[0].level + "' ";
    return dbSelectPromise(db, sql2);
  });
}

function getUsers() {
  let sql = "select distinct(user_id) from user_level_task";
  return dbSelectPromise(db, sql).then((users) => {
    return users;
  }).catch(() => {
    return [];
  });
}

cron.schedule('43 11 * * *', function () {

  var now = moment();
  var formatted = now.format('YYYY-MM-DD HH:mm:ss');

  getUsers().then((users) => {
    let batches = _.map(users, function (user) {
      return process(user);
    });
    return Promise.all(batches);
  }).then((fourthResult) => {
    console.log('Your fourthResult [[],..]', fourthResult);
  }).catch(() => {
    console.log('err while processing', err);
  });
});
Sridhar
  • 11,466
  • 5
  • 39
  • 43