【问题标题】:how to promises in a loop?如何在循环中承诺?
【发布时间】:2017-09-18 12:21:34
【问题描述】:

我正在尝试在 nodejs 中编写一个 cron 函数,该函数从数据库中获取所有用户的 user_id,然后我想解析每个 user_id。

这是我的代码:

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])
          }
        })
      })
     }
    })
});

我面临的问题是我无法在第三和第四个承诺中访问 i 的值。请帮忙!

【问题讨论】:

标签: node.js loops express promise


【解决方案1】:

我认为发生的事情是 i 在您创建这些新承诺时不再相同,因为 for 循环仍在运行。看来您真正需要的是user_idlevel_id。我建议你稍微重构你的代码以减少嵌套并传递你未来承诺所需的值。

也许类似这样:

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

它创建一个包含所有获取级别查询的数组作为承诺,然后使用Promise.all() 将其传递到下一步,只有在所有查询都成功的情况下才会解决。此时,您将可以再次访问每个结果的 userId,因为我们在新函数中为您的下一组查询返回了它。

我认为你应该进一步抽象你的查询,而不是使用通用的dbSelectPromise,并且不要忘记在最后catch(),否则你不会知道发生了什么。

注意:它假定您的 db 变量已正确实例化,并且您的原始 db.select 不需要根据您使用的任何库返回。那里还有一些新语法。

【讨论】:

    【解决方案2】:

    我面临的问题是我无法在第三个和第四个承诺中访问 i 的值。请帮忙!

    这是因为您正在使用重新初始化 i 而没有使用 let。当循环正在进行时,该值将与您的预期不同。

    每个promise相互依赖,需要同步运行

    为此,您需要链接承诺。此外,您可以使用Promise.all() 一次执行一堆承诺。请记住,Promise.all() 要么全有,要么全无。

    对您的代码进行这些更改,我得到以下结构。

    '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);
      });
    });
    

    【讨论】:

      猜你喜欢
      • 2018-10-13
      • 2020-05-15
      • 2023-03-17
      • 2021-08-12
      • 2018-03-25
      • 2014-01-09
      • 2014-03-12
      • 2020-05-14
      • 1970-01-01
      相关资源
      最近更新 更多