I have two functions in a blockchain contract to get the investors and funds for an address and tried to save that in Excel.
1st Function To get the list of investors:
getInvestorsList()
2nd Function This will take the investor address as input and returns the investor's address and the funds saved for that address:
getInvestorsAndBalances(address investorAddress)
I was able to get the list of investors and the funds sponsored by them using the functions getInvestorsList
and getInvestorsAndBalances
.
The below snippet, which convert the data to Excel has to executed only when the function getInvestorsAndBalances
executes completely for all investors. But this code is executed even before the call to the contract completes. Hence I am not getting the values from the blockchain to the below snippet.
How to make the below code wait for the successful completion of the function getInvestorsAndBalances
?
dataSample = dataSample + "]";
console.log("dataSample: " + dataSample);
//var dataSample = [{"address": "abc","balance": "21.22"}];
const xls = new XlsExport(dataSample, 'Example WB');
xls.exportToXLS('export.xls')
Complete Code
crowdSaleContractObj.getInvestorsList(function(error, result){
if(!error)
{
for (i=0; i < result.length; i++) {
crowdSaleContractObj.getInvestorsAndBalances(result[i],function(error, result1){
console.log(i);
if(!error)
{
console.log(i + " - Address : " + result1[0]+ ", Balance : " + result1[1]);
element = " {\"address\": " + result1[0] + ",balance:" + result1[1] + "},";
console.log("element: " + element);
dataSample = dataSample + element;
}
else
console.error(error);
});
}
dataSample = dataSample + "]";
console.log("dataSample: " + dataSample);
//var dataSample = [{"address": "abc","balance": "21.22"}];
const xls = new XlsExport(dataSample, 'Example WB');
xls.exportToXLS('export.xls')
}
else
console.error(error);
});
Here's a version of your code that works:
crowdSaleContractObj.getInvestorsList(function(error, results) {
if (!error) {
const promises = results.map(function(result, i) {
return new Promise((resolve, reject) => {
crowdSaleContractObj.getInvestorsAndBalances(result[i], function(
error,
result1
) {
console.log(i);
if (!error) {
console.log(
i + " - Address : " + result1[0] + ", Balance : " + result1[1]
);
resolve(result1);
} else {
console.error(error);
reject(error);
}
});
});
});
Promise.all(promises)
.then(function(results1) {
results1.forEach(r => {
element = ' {"address": ' + r[0] + ",balance:" + r[1] + "},";
console.log("element: " + element);
dataSample = dataSample + element;
});
dataSample = dataSample + "]";
console.log("dataSample: " + dataSample);
//var dataSample = [{"address": "abc","balance": "21.22"}];
const xls = new XlsExport(dataSample, "Example WB");
xls.exportToXLS("export.xls");
})
.catch(function(error) {
console.error(error);
});
} else console.error(error);
});
for
loop, I'm using Array.map to transform the results into an array of promises which resolve with the value returned to the callback in getInvestorsAndBalances
then
method to be executed only after all the investors and balances have been retrieved asynchronouslyImproving the Code
I've taken the liberty to refactor your code a bit to use modern language features and fix some mistakes:
crowdSaleContractObj.getInvestorsList((error, results) => {
if (error) {
console.error(error);
return;
}
const promises = results.map(
(result, i) =>
new Promise((resolve, reject) => {
crowdSaleContractObj.getInvestorsAndBalances(
result[i],
(error, result1) => {
if (error) {
reject(error);
return;
}
resolve(result1);
}
);
})
);
Promise.all(promises)
.then(results1 => {
const dataSample = `[${results1
.map(r => `{"address": "${r[0]}", "balance": ${r[1]}}`)
.join(", ")}]`;
const xls = new XlsExport(dataSample, "Example WB");
xls.exportToXLS("export.xls");
})
.catch(function(error) {
return console.error(error);
});
});
dataSample
with const; you didn't declare it at all, neither i
or element
, which made them global variables – this is a bad practicedataSample
string, combined with Array.join to avoid the problem of having a trailing comma at the end of the data (which caused invalid JSON format)