javascript - 在解决了包含嵌套 Promise 的 Promise 后执行代码

标签 javascript es6-promise web3js

我有以下js代码结构;

Promise_1.then(function(){
  for(){
    Promise2.then(function(){
      ...
    })
  }
}).then(
  Promise_3.then(function(){
    for(){
      Promise4.then(function(){
        ...
      })
    }
  })
).then(
  function(){
    // SOME CODE
  }
)

我想在上述 promise 得到解决后执行一些代码。但在上述 promise 得到解决之前,某些代码正在执行。我知道我可以在 setTimeout() 中包含一些代码,这将解决 SO 上其他答案所建议的问题,但我认为这不是一个好主意。我正在处理的实际代码如下;

user_xp = 0
connections_blocks.methods.get_deposit_blocks(current_email).call({
    from: new_web3.eth.Contract.defaultAccount
}, function (err, result) {
    deposit_blocks = result
    console.log(deposit_blocks)
    deposit_blocks = deposit_blocks.split(",")
    deposit_blocks.splice(0, 1)
    for (i_ in deposit_blocks) {
        console.log(deposit_blocks[i_])
        user_xp + new_web3.eth.getBlock(deposit_blocks[i_]).then(function (deposit_block) {
            user_xp = user_xp + deposit_block.gasUsed
            console.log(user_xp)
        })
    }
}).then(
    connections_blocks.methods.get_send_blocks(current_email).call({
        from: new_web3.eth.Contract.defaultAccount
    }, function (err, result) {
        send_blocks = result
        console.log(send_blocks)
        send_blocks = send_blocks.split(",")
        send_blocks.splice(0, 1)
        for (i_ = 0; i_ < send_blocks.length; i_ = i_ + 2) {
            console.log(send_blocks[i_])
            user_xp + new_web3.eth.getBlock(send_blocks[i_]).then(function (send_block) {
                user_xp = user_xp + send_block.gasUsed
                console.log(user_xp)
            })
        }
    })).then(
    setTimeout(function () {
        console.log(user_xp)
        xp = document.getElementById('xp')
        xp.innerHTML = "XP:" + user_xp
    },1000)
)

在上面的代码中,我只是使用 setTimeout() 来解决我的问题。但我希望代码仅在上述 promise 得到解决时自动执行。有没有简单的方法可以在 JS 中做到这一点,而无需在函数中添加 Promise 并使其变得更加复杂。

更新

我正在使用以下 web3 的函数从 Solidity 的智能合约中获取数据,该合约实际上返回一个 promise ,数据为 promiseValue

myContract.methods.myMethod([parameters).call(options,[callback])

最佳答案

您的代码存在问题

  1. .then 的参数必须是函数
  2. 如果需要在循环中等待Promise,则需要将它们添加到数组中,然后使用promise.all等待它们全部解决

尝试对您的实际代码进行以下更改 - 我假设如果没有节点样式回调,该函数将返回一个解析为结果的 promise 传递给节点样式回调(在此代码中已删除)

(如果您稍等一下,我会将 promise 链展平 - 只是注意到它并不像应有的那么平坦

user_xp = 0
return connections_blocks.methods.get_deposit_blocks(current_email).call({
    from: new_web3.eth.Contract.defaultAccount
})
.then(function (result) {
    var promises = []
    deposit_blocks = result
    console.log(deposit_blocks)
    deposit_blocks = deposit_blocks.split(",")
    deposit_blocks.splice(0, 1)
    for (i_ in deposit_blocks) {
        console.log(deposit_blocks[i_])
        promises.push(
            new_web3.eth.getBlock(deposit_blocks[i_]).then(function (deposit_block) {
                user_xp = user_xp + deposit_block.gasUsed
                console.log(user_xp)
            })
        )
    }
    return Promise.all(promises)
})
.then(function () {
    return connections_blocks.methods.get_send_blocks(current_email).call({
        from: new_web3.eth.Contract.defaultAccount
    })
})
.then(function (result) {
    var promises=[]
    send_blocks = result
    console.log(send_blocks)
    send_blocks = send_blocks.split(",")
    send_blocks.splice(0, 1)
    for (i_ = 0; i_ < send_blocks.length; i_ = i_ + 2) {
        console.log(send_blocks[i_])
        promises.push(
            new_web3.eth.getBlock(send_blocks[i_]).then(function (send_block) {
                user_xp = user_xp + send_block.gasUsed
                console.log(user_xp)
            })
        )
    }
    return Promise.all(promises)
})
.then(function () {
    console.log(user_xp)
    xp = document.getElementById('xp')
    xp.innerHTML = "XP:" + user_xp
})

作为一个额外的“奖励”,我相信代码可以简化为

return connections_blocks.methods.get_deposit_blocks(current_email).call({
    from: new_web3.eth.Contract.defaultAccount
})
.then(result => Promise.all(result.split(",").slice(1).map(deposit_block => new_web3.eth.getBlock(deposit_block)
    .then(deposit_block => deposit_block.gasUsed)
})
.then(gasUsed1Array => connections_blocks.methods.get_send_blocks(current_email).call({
        from: new_web3.eth.Contract.defaultAccount
    })
    .then(result => Promise.all(result.split(",").slice(1).filter((v, i) => !(i%2)).map(send_blocks => new_web3.eth.getBlock(send_block)
        .then(send_block => send_block.gasUsed)
    )))
    .then(gasUsed2Array => [...gasUsed1Array, ...gasUsed2Array])
)
.then(results => {
    user_xp = results.reduce((a, b) => a + b);
    console.log(user_xp)
    xp = document.getElementById('xp')
    xp.innerHTML = "XP:" + user_xp
})

关于javascript - 在解决了包含嵌套 Promise 的 Promise 后执行代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59482652/

相关文章:

javascript - 为什么我的异步 Jest 测试没有在应该失败的时候失败?

solidity - Remix IDE 不显示子契约(Contract)

javascript - 如何使用Web3购买ERC20代币

javascript - Codeigniter:AJAX调用后返回JSON数据但无法运行success: function()

javascript - 在最后一个点之后匹配文本中的字符串

javascript - 我如何执行一大批 promise ?

ethereum - 获取/猜测未验证合约的外部方法

javascript - javascript 中的流畅服务 API

javascript - CSS 样式属性留空

javascript - 如何使用 JS Promise 处理异步调用?