在带有嵌套promise的promise之后执行代码

问题描述 投票:0回答:2

我具有以下js代码结构;

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

我想在上述承诺解决后执行一些代码。但是,在上述承诺得到解决之前,正在执行某些代码。我知道我可以在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()来解决我的问题。但是我希望代码仅在上述承诺得到解决时才自动执行。没有任何简单的方法可以在JS中做到这一点,而不必在函数中添加承诺并使其更加复杂。

UPDATE

[我正在使用以下web3的功能从实体的智能合约中获取数据,该合约实际上返回了一个以promiseValue为数据的承诺

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

javascript es6-promise web3
2个回答
1
投票

我假设Promise_1和Promise_3的解析将等待回调完成。如果是这种情况,这应该可以工作。

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)
    // array to hold the promises
    const subPromises = []
    for (i_ in deposit_blocks) {
        console.log(deposit_blocks[i_])
        subPromises.push(new_web3.eth.getBlock(deposit_blocks[i_]))
    }
    // waiting for all promises to resolve
    Promise.all(subPromises).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)
        const subPromises = []
        for (i_ = 0; i_ < send_blocks.length; i_ = i_ + 2) {
            console.log(send_blocks[i_])
            subPromises.push(
                new_web3.eth.getBlock(send_blocks[i_])
            )
        }
        Promise.all(subPromises).then(function (send_block) {
            user_xp = user_xp + send_block.gasUsed
            console.log(user_xp)
        })
    })
)
.then(function () {
    console.log(user_xp)
    xp = document.getElementById('xp')
    xp.innerHTML = "XP:" + user_xp
})

1
投票

您的代码存在的问题

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

对您的actual代码进行以下更改-我假设没有节点样式回调,该函数将返回一个承诺,该承诺将解析为将传递给节点样式回调的result(在此代码中删除)

<<

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

© www.soinside.com 2019 - 2024. All rights reserved.