2

Using Web3.js, how do I call a function on multiple instances of a contract and then store their results in an array? I've tried .map and .forEach, but they don't return the objects I expected.

I am able to get a desirable result when I call the function on one instance:

let giftStats = await SmartGift(
        '0xbb6810057e1D82deE83A981b002F2E0C60293a27'
    )
        .methods.getGiftStats()
        .call()



console.log(giftStats)

Result { '0': '0xfAA7541C5cBe22E4518736D2b5fC34D07347eE45', '1': '0x0000000000000000000000000000000000000000', '2': '0x0000000000000000000000000000000000000000', '3': '0', '4': '0', '5': '0', '6': '100', '7': '0', '8': false, '9': false, '10': '' }

I'm looking for a method that enables me to store two objects like the one above in an array. But when I try to call map() or forEach() on an array of addresses, the resulting array is not what I'd expect.

ATTEMPT 1: .map( )

const recipientGifts = ['0xAEaadCd9499127Ae0826aC2E918372927E4B55D4','0xbb6810057e1D82deE83A981b002F2E0C60293a27']    
let giftStats = await recipientGifts.map((address) => {
JSON.stringify(
    SmartGift(address)
    .methods.getGiftStats()
    .call()
)
console.log(giftStats)  

[ undefined, undefined ]

ATTEMPT 2: .forEach( )

const recipientGifts = ['0xAEaadCd9499127Ae0826aC2E918372927E4B55D4','0xbb6810057e1D82deE83A981b002F2E0C60293a27']  
let giftStats = []
await recipientGifts.forEach((address) =>giftStats.push(SmartGift(address)  
    .methods.getGiftStats() 
    .call() ))

console.log(giftStats)

[ Promise { _bitField: 0, _fulfillmentHandler0: undefined, _rejectionHandler0: undefined, _promise0: undefined, _receiver0: undefined }, Promise { _bitField: 0, _fulfillmentHandler0: undefined, _rejectionHandler0: undefined, _promise0: undefined, _receiver0: undefined } ]

3 Answers 3

0

The second method is pretty close but you should try to put the await inside the forEach since that would return a promise

await recipientGifts.forEach(async(address) => giftStats.push(await SmartGift(address)  
    .methods.getGiftStats() 
    .call() ))
3
  • I just tried this, but it returns an empty array. Mar 22, 2018 at 14:09
  • I think probably forEach doesn't support promises. Just use a normal loop instead, gonna be ok
    – qbsp
    Mar 22, 2018 at 14:17
  • Yeah, after incorporating your suggestion, I replaced the .forEach( ) with a for loop, and it works! Thanks! Mar 22, 2018 at 14:17
0

I originally wanted to solve this using only functional programming, avoiding loops. But I got it to work using a for loop.

let giftStats = []
    for (let i = 0; i < recipientGifts.length; i++) {
        giftStats.push(
            await SmartGift(
                recipientGifts[i])
                .methods.getGiftStats()
                .call()
        )
    }

console.log(giftStats)
[ Result { '0': '0xfAA7541C5cBe22E4518736D2b5fC34D07347eE45', '1': '0x0000000000000000000000000000000000000000', '2': '0x0000000000000000000000000000000000000000', '3': '0', '4': '0', '5': '0', '6': '5000', '7': '0', '8': false, '9': false, '10': '' }, Result { '0': '0xfAA7541C5cBe22E4518736D2b5fC34D07347eE45', '1': '0x0000000000000000000000000000000000000000', '2': '0x0000000000000000000000000000000000000000', '3': '0', '4': '0', '5': '0', '6': '100', '7': '0', '8': false, '9': false, '10': '' } ]

0

A functional way to do this is by combining Array.map with Promise.all:

const array = await Promise.all(
  recipientGifts.map((address) =>
    SmartGift(address)
      .methods.getGiftStats()
      .call()
);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.