I’m fluent in JS, and have some experience with Solidity and Elixir.
From JS POV, this behavior is very normal. Let’s map the logic into some concrete JS code:
class Actor {
balance = 0
async whenZeroBalance() {
if (this.balance == 0) {
await scrapeFund()
console.log("current balance:", this.balance)
}
}
// after 10sec, 1000 is magically added to balance.
async scrapeFund() {
await sleep(10000)
this.balance += 1000
}
async topUp(amount) {
this.balance += amount
}
}
What happen if Alice calls whenZeroBalance()
then Bob calls topUp(999)
? We’ll see "current balance: 1999"
. This is intended, as we explicitly shared this.balance
(@nerdoutcj yes, in this case it’s shared, you’re right) across multiple method calls. With this syntax we voluntarily share state.
However, we can opt to another model.
class Actor {
_updateBalance(updater) {
this.balance = updater(this.balance)
}
balance = 0
async whenZeroBalance() {
const balance = this.balance
if (balance == 0) {
const newBalance = await scrapeFund(balance)
console.log("current balance:", newBalance)
// sync state
this._updateBalance((currBalance) => {
if (currBalance == 0) {
return newBalance
} else {
const delta = newBalance - balance
return currBalance + delta
}
})
}
}
// after 10sec, 1000 is magically added to balance.
async scrapeFund(prevBalance) {
await sleep(10000)
return prevBalance + 1000
}
async topUp(amount) {
this.balance += amount
}
}
If we avoid referencing this.balance
across await, and instead use the balance variable in closure, you don’t have to worry about it “surprisingly” changed after await.
What feels unnatural (surprising) to me at first sight of Motoko, is because of the mindset formed from past experience with Solidity. In Solidity each transaction is actually sync call, even across multiple contracts. Asynchrony doesn’t exit in Solidity’s model.
My thought about it is that, Motoko/Dfinity brings about a paradigm shift of computation model in blockchain, that’s a feature by design. And with power comes responsibility. We have concurrency and scaling ability, now we have to deal with state synchronization.