Lets say items are frequently added via push into an array. Another async function(which runs independently in a setInterval context) removes random items from the array.
In this second function, when in one line I evaluate the index of the item to be removed, the array could change before I reach the next line where I do array.splice(index, 1). Correct? The wrong item would be removed.
How should I solve that?
EDIT: example:
async function analyze() {
let pendingTxs = []
web3.eth.subscribe('pendingTransactions', function(error, result){
if (error) console.log(error);
})
.on("data", async function(hash){
pendingTxs.push(hash)
})
setInterval(async () => {
let promises = pendingTxs.map(pTx => {return web3.eth.getTransaction(pTx)})
let updatedTransactions = await Promise.all(promises)
for (let index = 0; index < updatedTransactions.length; index ) {
const txUpdated = updatedTransactions[index];
if (txUpdated.transactionIndex != null) {
const index = pendingTxs.indexOf(txUpdated.hash)
if (index > -1) {
pendingTxs.splice(index, 1);
}
}
}
},250)
}
analyze()
EDIT2: I think Chris may be right in this case.
CodePudding user response:
No.
const index = pendingTxs.indexOf(txUpdated.hash)
if (index > -1) {
pendingTxs.splice(index, 1);
}
runs as a unit.
JavaScript's async
functions are cooperative, not preemptive.
"Difference between Preemptive and Cooperative Multitasking"
In cooperative multitasking, the [controller] never initiates context switching from the running [thread] to another [thread]. A context switch occurs only when the [thread] voluntarily yields control
since JS is based on event loop concurrency
So if you do an await
or yield
, then other code may run, but if you do not explicitly do one of those pausing actions, then the instructions above run as a unit.
SharedArrayBuffers are an exception to this because the host is allowed to share their contents widely, but Arrays are not so shared.