how to detect errors in web3.js

Viewed 2456

this is my code

for(var i = 0 ; i <= 4 ; i++){
myContract.methods.contractmanager(i).call().then((res)=>{
console.log(res[0]);
}):
}

there is 2 data stored in my contract and i want to print it but it is not always 2 and it will be more and dynamic and i wont know how many they will be. after executing this code i have 2 output and 2 error. how to make the loop stop at 2 and it wont show the errors? how to detect the error and break the loop? how to find out if the output is empty or not? solidity code:

function contractmanager(uint i) public view returns(uint , address , address , uint , uint , uint){
            return (contrs[list_contr[i]].idc , contrs[list_contr[i]].seller , contrs[list_contr[i]].buyer, contrs[list_contr[i]].price ,contrs[list_contr[i]].date , contrs[list_contr[i]].pos );
    }
2 Answers

The EVM throws an exception when you're trying to access an item of an array with higher index than the array length. It's basically the same thing as "array index out of bounds" exception in other languages.

You'll need to create a separate function to get the array length (see myArrayLength() in the example below) and perform the length check in your JS code this way.


Example:

Solidity

pragma solidity ^0.8;

contract MyContract {
    uint256[] public myArray;
    
    function addToArray(uint256 _value) external {
        myArray.push(_value);
    }
    
    function myArrayLength() external view returns (uint256) {
        return myArray.length;
    }
}

Node.js

const Web3 = require('web3');

const WEB3_PROVIDER = 'http://127.0.0.1:7545/';
const ABI_JSON = [{
    "inputs": [{"internalType": "uint256", "name": "_value", "type": "uint256"}],
    "name": "addToArray",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
}, {
    "inputs": [{"internalType": "uint256", "name": "", "type": "uint256"}],
    "name": "myArray",
    "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}],
    "stateMutability": "view",
    "type": "function"
}, {
    "inputs": [],
    "name": "myArrayLength",
    "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}],
    "stateMutability": "view",
    "type": "function"
}];
const CONTRACT_ADDRESS = '0xCc0607EfdF166344fc94589a61F09dcFbC89B1a7';
const FROM_ADDRESS = '0x8553DA9C81f940041ee4F46c14e2C7b20ad32F8C';

const run = async () => {
    const web3 = new Web3(WEB3_PROVIDER);
    const contract = new web3.eth.Contract(ABI_JSON, CONTRACT_ADDRESS);

    await contract.methods.addToArray(123).send({from: FROM_ADDRESS}); // sets the first item

    const firstItem = await contract.methods.myArray(0).call(); // retrieves the item with index 0 (the existing, first item)
    console.log(firstItem);

    try {
        const otherItem = await contract.methods.myArray(100).call(); // tries to retrieve the item with index 100 (non-existing)
    } catch (e) {
        console.log("Failed");
    }

    const length = await contract.methods.myArrayLength().call();
    console.log(length);
}

run();

Console output

123
Failed
1

You could use the ".catch()" method like in the following code :

async function getBlockInfo(i) {
    await web3.eth.getBlock(i).then(block => {
        block.transactions.forEach(function (t) {
            web3.eth.getTransaction(t).then(transaction => {
                console.log(i + ' ' + transaction.hash + ' ' + transaction.from + ' ' + transaction.to)
            }).catch((error) => {
                console.log('erreur')
            })
        })
    }).catch((error) => {console.log(error)})
}
Related