Most programs provide an “Autosave” feature these days. The feature gives the user a chance to minimize the amount of work lost due to some unforeseen mishap, like a sudden power outage.
When I write a program in Clojure that requires such a feature, I have the entire Java library at my disposal. I usually create something based on a
ScheduledExecutorService – something that watches for a change in the document then allows a certain amount of user inactivity to pass before automatically saving the document. If the user makes another revision before the executor is triggered, the executor timer is reset to trigger after another period of inactivity.
When programming in ClojureScript, those concurrency facilities are not available. Instead, I came up with something like the following.
(def delay-handle (atom nil)) (defn clear-autosave-delay!  (.clearTimeout js/window @delay-handle)) (defn start-autosave-delay! [doc-save-fn delay-ms page-map-atom] (reset! delay-handle (.setTimeout js/window doc-save-fn delay-ms page-map-atom))) (defn change-watcher! [doc-save-fn page-map-atom] (let [delay (* 1000 (get-in @page-map-atom [:options :editor_autosave_interval]))] (when (pos? delay) (clear-autosave-delay!) (start-autosave-delay! doc-save-fn delay page-map-atom))))
I put the
change-watcher! function in the
:on-change handler for a control (or multiple controls). Whenever a change occurs, it resets the delay. If the delay expires, the
doc-save-fn is called to do the save.
It isn’t very “Clojuresque,“ but it does seem to work ok.