【问题标题】:Unable to resolve promise chain无法解决承诺链
【发布时间】:2018-04-25 08:22:58
【问题描述】:

我正在尝试编写一个 Sequelize 迁移脚本 win,我正在尝试更新我的数据库,但它有许多异步操作(数据库查询,然后更新具有特定 id 的数据库)

这是我的代码

return db.organizationEntries
      .findAll()
      .then((entries) => {
        return entries.forEach(entry => {
          console.log(entry);
          db.organizationEntries
            .findAll({
              attributes: [
                [
                  db.sequelize.fn(
                    'MAX',
                    db.sequelize.col('organizationEntries.serial_number')
                  ),
                  'maximum_serial_no'
                ]
              ],
              where: {
                organizationId: entry.organizationId
              }
            })
            .then(orgEntry => {
              console.log(orgEntry[0].dataValues.maximum_serial_no);
              let data = { serialNumber: orgEntry[0].dataValues.maximum_serial_no + 1 };
              console.log(data)

              //problem 
              db.organizationEntries.update(data, {
                where: {
                  id: entry.id
                }
              })
                .then((result) => {
                  console.log(result);

                })
            });
          // promises.push(promise);
        });
        // return Promise.all(promises);
      }) 

实际上我想要做的是我试图从数据库中获取所有orgEntries 的列表,然后我找到那个organization_id 的最大序列号,然后更新那个特定的 orgEntry,就像所有这些循环操作

现在问题来了,所有事情都按顺序进行,但是在找到 max_serial_no 之后,它没有更新数据库,我无法解决我应该做些什么来使异步调用按此顺序工作

【问题讨论】:

  • return entries.forEach 不会做你想做的事 - forEach 返回未定义。你的// promises.push(promise); 相关吗?
  • 是的,它不会返回任何东西
  • @CertainPerformance 我试图将此更新放入 Promise.all() 但我想按顺序发生所有事情,因为我已经提到过其他错误的 max_serial_no 会出现
  • @CertainPerformance 我试过 async 和 await 但没用
  • 报错

标签: javascript promise sequelize.js es6-promise ecmascript-5


【解决方案1】:

我认为你可以通过两种方式解决这个问题:

同时承诺

在下面的代码中,我删除了 forEach 以支持 Promise.all() 和 map()

  • map() 方法创建(并返回)一个新数组,其结果是在调用数组中的每个元素上调用提供的函数。

例子:

let numbers = [1, 2, 3]
let doubledNumbers = numbers.map(n => n * 2)
// doubledNumbers [2, 4, 6]
  • Promise.all() 方法将一组 Promise 作为参数,并返回一个 Promise,当所有 Promise 都将被解析时,该 Promise 将被解析;如果一个 Promise 失败,则该 Promise 将被拒绝

例子:

let promise1 = findUserById(5)
let promise2 = findUserFriends(5)
Promise.all([promise1, promise2])
.then(values => {
  // values: [user object, list of user friends]
})

结果:

db.organizationEntries.findAll()
.then(entries => {
  return Promise.all(entries.map(entry => {
    console.log(entry)

    return db.organizationEntries.findAll({
      where: {
        organizationId: entry.organizationId
      },
      attributes: [
        [
          db.sequelize.fn('MAX', db.sequelize.col('organizationEntries.serial_number')),
          'maximum_serial_no'
        ]
      ]
    })
    .then(orgEntry => {
      console.log(orgEntry[0].dataValues.maximum_serial_no)
      let data = { serialNumber: orgEntry[0].dataValues.maximum_serial_no + 1 }
      console.log(data)
      return db.organizationEntries.update(data, { where: { id: entry.id } })
    })
  }))
})
.then(result => {
  // result: Array of updated organizationEntries
  console.log(result)
})

使用reduce() 方法逐步承诺

  • reduce() 方法对累加器和数组中的每个元素(从左到右)应用函数以将其减少为单个值。 (来自 MDN 网络文档)

例子:

let items = [{ name: 'pencil', price: 2 }, { name: 'book', price: 10 }]
let total = items.reduce((total, item) => total += item.price, 0)
// total: 12

结果:

db.organizationEntries.findAll()
.then(entries => {
  return entries.reduce((previousPromise, entry) => {
    console.log(entry)

    return previousPromise
    .then(_ => {
      return db.organizationEntries.findAll({
        where: {
          organizationId: entry.organizationId
        },
        attributes: [
          [
            db.sequelize.fn('MAX', db.sequelize.col('organizationEntries.serial_number')),
            'maximum_serial_no'
          ]
        ]
      })
    })
    .then(orgEntry => {
      console.log(orgEntry[0].dataValues.maximum_serial_no)
      let data = { serialNumber: orgEntry[0].dataValues.maximum_serial_no + 1 }
      console.log(data)
      return db.organizationEntries.update(data, { where: { id: entry.id } })
    })
    .then(updatedEntry => {
      console.log(updatedEntry)
    })
  }, Promise.resolve())
})
.then(result => {
  // result: Last updated organization entry
  console.log('finished')
})

【讨论】:

  • 嗨,Carmelo,感谢您的回答 - 您能详细说明为什么会这样吗? (我们为什么要Promise.alling entries.map?)
  • Promise.all() 会同时进行所有更新,但我想要一个一个
  • @Vikas 哦,好吧!只需将map() 方法替换为reduce()。我很快就会写例子。
  • @NiritLevi 这是一个反问,试图让 Carmelo 在答案中解释这一点,但谢谢 :)
猜你喜欢
  • 1970-01-01
  • 2018-09-23
  • 2014-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-18
  • 2019-05-09
  • 2019-07-21
相关资源
最近更新 更多