First off, apologies for the giant wall of text. There probably isn’t a direct, straightforward answer to your question in here, but if you need something to ponder while you wait for better answers, continue on.
I don’t know which if any of these things are actually responsible for the behavior you’re seeing, and you’re totally free to ignore my opinions, because they are admittedly arbitrary rules that are designed solely to prevent me from making mistakes that I have made in the past.
That being said,
- I only read from device storage (whatever the implementation) once per app run.
checkGender breaks that rule.
- I also never touch device storage from pages, only services.
- Finally, I never bind multiple handlers to the same event. You’ve got two on
I would be interested to know if rearchitecting the code to follow these rules magically designs away your problem here. There are two reasons that I think it might.
I don’t know if there is an officially-defined execution order when multiple handlers are present on an event binding, but I strongly feel that acting as if it were totally unspecified is the safest thing for app code to do. If we invert the order of the assignment to
userMale and the call to
onChangeGender, I think we would get surprising behavior. (Incidentally, I think you are likely to run into trouble attempting to represent gender as a mere boolean). So here’s a situation where you might be inadvertently storing stale data.
The liberal use of
await (another thing I avoid, largely because of situations like this) obscures this, but
setGender returns a
Promise that is silently ignored by
onChangeGender. You have no guarantee that
checkGender has completed (either its read or its write) when
In summary, I would redesign this so that:
- all interaction with storage happens only in a service
- reads happen only at app startup (or the first time the data is requested)
- gender is stored as a string, not a boolean
- do the assignment to
userMale manually in your
ngModelChange handler instead of banana-binding
(ngModel), so you know when it happens
I applaud your decision to test this by force-quitting the app, because it exposes the futility of attempting to protect device storage referential integrity at write time. The reason I have the “do not read from storage more than once per app run” rule is that it allows me to blissfully ignore
Promises from write operations. I don’t have to worry about the following scenario:
A. “foo” is sitting in storage.
B. live data becomes “bar”.
C. initiate write to storage for “bar”.
D. read from storage.
E. maybe we get new “bar”, maybe we get old “foo”.
If I never do D, the problem in E can’t happen. I never do D, because the only time I read from storage would be before B.
There is an alternative strategy here, which would be to ensure that C completes before D is allowed to start. I reject this strategy for two reasons, one of which you shined a light on here. First, it needlessly blocks the CPU. The live service, which should be the only source of truth for all the pages in the app, already knows that the new value is “bar”. It doesn’t have to wait to write it to storage and read it back again. The second reason is that it’s always possible that the app will get force quit while the write is pending, and there is absolutely no way to either block that or know about it from inside the app, so it’s pointless to try to address it directly.