This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the web-development category.
Last Updated: 2024-12-03
Background: My software uses JavaScript to update the flash messages of pages that use public caching rather using than HTML (so as to avoid caching the message and showing it to the wrong user).
In a refactor, I changed from sending an array of flash_messages
...
def update_flash
payload = {
flash_messages: [flash_messages]
}.to_json
render json: payload
end
...to sending null if no messages are present:
def update_flash
payload = {
flash_messages: @flash ? nil : [flash_messages]
}.to_json
# if null, this would give the following json:
# => {"flash_messaages":null}
render json: payload
end
My old JavaScript client side had the following:
if (Object.keys(data.flash_messages).length > 0) {
updateFlash()
}
When a something passed to Object.keys
has a null value, as it could have
after the rewrite, Object.keys
throws an error. This did not happen in the old
code because I was guaranteed a non-null object.
Therefore I changed the client code to handle this.
if (data.flash_messages) {
data.flash_messages(displayMessage)
}
Yet - and here's the point of this piece - I still got a deluge of exceptions. Why? My guess is that I had publicly cached some webpages referencing the old JavaScript file. This old JavaScript made a request to the modified backend and got the new response, but couldn't handle it.
Client-side updates that are supposed to be in lock-step with backend changes may lead to issues caused by out-of-data code that is cached.
This problem is worse with SPAs where the code may not refresh at the browser level for quite some time.
Proactive solutions: - support both old and new way for some time (but leave a deprecation notice) - reduce cache time for assets generally (or just in the time before deploying)