Search code examples
structnullmappingsolidityweb3js

the mapping struct return null by web3


Now I try to do the solidity to save the struct data, and retrieve the data by mapping string in web3 interface.

Now I've finished the data saving part, and I can get the data in my Remix API, but if I wanna get the data by web3, it'll return null as following:

enter image description here

the version of the web3 is 1.3.4. I once tried whether I can return the data in the function of saving data and it worked, thus I guess that the data isn't shared by functions in web3...

and I found out this problem, but I still can't get the solution.

the following is the code:

pragma solidity >=0.7.0 <0.9.0;

contract Storage{
    string b = "calculation a";
    
    struct UserInfo {
        string time;
        uint emission;
    }
    mapping (string => UserInfo) public users;

    function saveData(string memory input_time, string memory input_source, string memory input_mycalculate, uint input_material) public{
        users[input_source].time = input_time;
        if (keccak256(abi.encodePacked(input_mycalculate)) == keccak256(abi.encodePacked(b)))
            users[input_source].emission = input_material * 3 / 2;
        else
            users[input_source].emission = input_material * 5 / 2;
    }
    
    function search(string memory input_source) public view returns (UserInfo memory) {
        return users[input_source];
    }
} 

and the following is the js code to show the data:

contract.methods.search(input_company).call({from:web3.eth.defaultAddress})
  .then((result) => {
        console.log(result)
        companyResultLineChart.innerHTML += result[0] + result[1]
  })

Solution

  • It should be an timing issue. It is a asynchronous JavaScript code so you have to use ".then" or await. In Your code example you are using ".then". I used saveData function with "60sec", "test_src", "calc", "10" for testing purpose. So below code:

    console.log("------ before then ------ ")
    let innerHTML = "HTML "
    contract.methods.search("test_src").call().then((result) => {
       console.log(innerHTML)
       innerHTML += result[0] + result[1] 
       console.log(result)
       console.log(innerHTML)
       
    })
    
    console.log("------ after then ------ ")
    

    will type in console:

    ------ before then ------ 
    ------ after then ------ 
    HTML 
    [ "60sec", "25" ]
    HTML 60sec25
    

    Code with await:

    console.log("------ before await ------ ")
    let innerHTML2 = "HTML "
    let result_async = await contract.methods.search("test_src").call();
    console.log(innerHTML2)
    innerHTML2 += result_async[0] + result_async[1] 
    console.log(result_async)
    console.log(innerHTML2)
    console.log("------ after await ------ ")
    

    will type in console:

    ------ before await ------ 
    HTML 
    [ "60sec", "25" ]
    HTML 60sec25
    ------ after await ------