Reputation: 861
I have the following js code structure;
Promise_1.then(function(){
for(){
Promise2.then(function(){
...
})
}
}).then(
Promise_3.then(function(){
for(){
Promise4.then(function(){
...
})
}
})
).then(
function(){
// SOME CODE
}
)
I want to execute SOME CODE after the above promises are resolved. But the SOME CODE is executing before the above promises are resolved. I know I can enclose SOME CODE in setTimeout()
which will solve the problem as suggested by other answers on SO but I think it's not a good idea. The actual code on which I am working is as follow;
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)
)
In the above code, I am just using setTimeout()
which is solving my problem. But I want the code to execute automatically only when the above promises are resolved. Is there any easy way to do that in JS w/o putting promises in functions and making it more complex.
UPDATE
I am using the following web3's function to fetch data from the solidity's smart contract which actually returns a promise with the data as promiseValue
myContract.methods.myMethod([parameters).call(options,[callback])
Upvotes: 0
Views: 67
Reputation: 1
Problems with your code include
Try the following changes to your actual code - I'm assuming that without the node style callback, the function returns a promise that resolves to the result
that would be passed to the node-style callback (which is removed in this code)
(if you wait a while I'll flatten the promise chain - just noticed it isn't as flat as it could be
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
})
As an added "bonus", I believe the code can be simplified to
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
})
Upvotes: 1
Reputation: 383
I presume that the resolve of Promise_1 and Promise_3 will wait for the callbacks to complete. If this is the case, this should work.
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
})
Upvotes: 1