簡體   English   中英

在解析包含嵌套承諾的承諾之后執行代碼

[英]Executing a code after a promise with nested promises inside it is resolved

我有以下js代碼結構;

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

我想在解決上述承諾后執行一些代碼。 但是在解決上述承諾之前,SOME CODE 正在執行。 我知道我可以在setTimeout()附上一些代碼,這將解決其他答案所建議的問題,但我認為這不是一個好主意。 我正在處理的實際代碼如下;

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 中做到這一點,而無需在函數中放置 Promise 並使其更加復雜。

更新

我正在使用以下 web3 的函數從 Solidity 的智能合約中獲取數據,該合約實際上返回一個承諾,數據為promiseValue

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

我認為 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. .then 的參數必須是函數
  2. 如果需要等待循環中的 Promises,則需要將它們添加到數組中,然后使用 promise.all 等待它們全部解析

請嘗試以下更改實際的代碼-我假設,如果沒有節點樣式的回調,該函數返回一個承諾,解析到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
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM