Reputation: 113
I am attempting to modify the masterCounter
variable within the timeKeyAdditionCheck
function. Within the timeKeyAdditionCheck
function, I successfully assign a value to masterCounter
, but this change is not reflected within the scope of getEventsWithTime
. When timeKeyAdditionCheck
is complete, the value of masterCounter
returns to null.
What changes do I need to make with timeKeyAdditionCheck
function?
let masterCounter = null;
let userTracker = {};
let timeKeyAdditionCheck = ('hour') => {
assert((range == 'minute' || range == 'hour'), "In calcArrayof... range value needs to equal 'minute' or 'hours'")
if (masterCounter == null) {
masterCounter = [{timerange: event.timestamp, totalusercount: 0, totalvalidatorcount: 0, totaletherdeposited: 0}]
}
if (event.timestamp > (masterCounter[masterCounter.length - 1] + 3599)) {
let differenceInTime = event.timestamp - (masterCounter[masterCounter.length - 1] + 3599);
let timeKeysNeeded = Math.ceil(differenceInTime / 3600);
i = 0;
while (i < timeKeysNeeded) {
let newEntry = masterCounter[masterCounter.length - 1];
newEntry.timerange = newEntry.timerange + 3600;
masterCounter.push(newEntry);
i++;
}
}
}
(async () => {
let events = await getEventsWithTime(3085928,3089928);
for (event of events) {
timeKeyAdditionCheck('hour');
checkNewUsers();
addValidatorsAndEth();
}
convertToCsv(masterCounter)
console.log(masterCounter)
})()
Upvotes: 0
Views: 56
Reputation: 113
The reason I wasn't getting the expected output for masterCounter
was because, in the timeKeyAdditionCheck
function, I thought I was making a copy of the object in the masterCounter
array, but I actually created a reference instead. Here is the moment in my code when I unintentionally created a reference instead of a copy:
let newEntry = masterCounter[masterCounter.length - 1];
When I thought I was adding a unique object to the array, I was instead adding the reference to that same object at the end of the array.
I fixed it using the following code:
while (i < timeKeysNeeded) {
let lastObjectRef = masterCounter[masterCounter.length - 1];
let newEntry = Object.assign({}, lastObjectRef)
newEntry.timerange = newEntry.timerange + 60;
masterCounter.push(newEntry);
i++;
}
I used Object.assign()
to create a copy of the last object in the array instead of creating another reference.
Upvotes: 0
Reputation: 65796
Because masterCounter
is not declared within timeKeyAdditionCheck
(it's assigned there, but not declared there), masterCounter
is implicitly declared as a Global variable. But, in getEventsWithTime
, you do declare masterCounter
so that declaration "hides" the Global one and is treated as a completely separate variable.
You need masterCounter
to be declared in a higher scope than either of the two functions so that both can have access to it, or you could pass masterCounter
to the getEventsWithTime
function as an argument.
// By declaring the variable in a higher scope than either of the functions
// that need access to it, both can find it and use it.
let masterCounter = null // later turns into an array
let timeKeyAdditionCheck = (event, range, masterCounter) => {
assert((range == 'minute' || range == 'hour'), "In calcArrayof... range value needs to equal 'minute' or 'hours'")
if (masterCounter == null) {
masterCounter = [{timerange: event.timestamp, totalusercount: 0, totalvalidatorcount: 0, totaletherdeposited: 0}]
}
if (event.timestamp > (masterCounter[masterCounter.length - 1] + 3599)) {
let differenceInTime = event.timestamp - (masterCounter[masterCounter.length - 1] + 3599);
let timeKeysNeeded = Math.ceil(differenceInTime / 3600);
i = 0;
while (i < timeKeysNeeded) {
let newEntry = masterCounter[masterCounter.length - 1];
newEntry.timerange = newEntry.timerange + 3600;
masterCounter.push(newEntry);
i++;
}
}
}
let getEventsWithTime = async (firstBlock, lastBlock, range) => {
try {
let userTracker = {};
let events = await depositContract.getPastEvents('DepositEvent', {fromBlock: firstBlock, toBlock: lastBlock}) // 2845084 2846000
for (event of events) {
let results = await web3.eth.getBlock(event.blockNumber);
event.timestamp = results.timestamp;
timeKeyAdditionCheck(event, range, masterCounter);
checkNewUsers(event, userTracker, masterCounter);
addValidatorsAndEth(event, userTracker, masterCounter);
}
convertToCsv(masterCounter)
console.log(masterCounter)
} catch(error) {
console.log(error);
}
}
Also, see this post of mine, which explains the "scope chain" and illustrates this issue in more detail.
Upvotes: 1
Reputation: 101
You should declare masterCounter in a scope which contains both functions that are going to use it.
For example, you could declare masterCounter immediately preceding when you declare either function (assuming they are in the same scope).
A sign that your declarations are incorrect is the check to see if masterCounter is null. For it to be shared outside of these functions, it can never be null when the function attempts to access or set it.
Upvotes: 0