Ich versuche, einen Dateipreloader innerhalb von ClojureScript zu erstellen. Meine Idee war, ein Muster wie folgt aus:ClojureScript Datei Preloader - Funktion oder Muster, um Versprechen zu emulieren?
(def urls (atom[]))
(def loaded-resources (atom []))
(def all-resources (promise))
(defn loading-callback []
(if (= (count urls) (count loaded-resources))
(deliver all-resources loaded-resources)))
;; fill urls array
;; start ajax-loading with loading-callback on success
So konnte meine Hauptfunktion weitergehen, bis sie die Ressourcen erfordern würde, und dann auf sie warten, die gut in Clojure funktioniert.
Leider gibt es keine Versprechungen in ClojureScript, also wie kann ich dieses Problem umgehen? Es gibt promesa Versprechen zu CLJS basierend auf core.async-Kanälen, aber es erlaubt nur zukunftsorientierte Versprechen, die auf die Ausführung einer einzelnen Funktion warten, die meinen Bedürfnissen nicht genügt (zumindest in der Art, wie ich gestern darüber nachgedacht habe) ...).
Irgendwelche Vorschläge, um dieses Problem zu lösen? Vielleicht ein ganz anderes Muster verwenden? Ich möchte den Code so einfach wie möglich halten, um die Leute in meinem Team davon zu überzeugen, CLJ/S auszuprobieren.
EDIT:
Nach Alans zweite Idee:
(def urls (atom[]))
(def loaded-resources (atom []))
(defn loading-callback [data]
(swap! loaded-resources conj data))
(defn load! [post-loading-fn]
(add-watch loaded-resources :watch-loading
(fn [_ _ _ cur]
(if (= (count cur) (count @urls)) (post-loading-fn))))
;; init ajax loading
)
(defn init []
;; fill urls array
(load! main))
(main []
(do-terrific-stuff @loaded-resources))
Inzwischen hatte ich versucht, core.async
(def urls (atom []))
(def loaded-resources (atom []))
(def resource-chan (chan))
(defn loading-callback [data]
(go (>! resource-chan data)))
;; fill url array from main
(load! []
;; init ajax loading
(go-loop []
(when-not (= (count @loaded-resources) (count @urls))
(swap! loaded-resources conj (<! resource-chan))
(recur)))
Nicht sicher besser, welche Version zu verwenden ist.
Verwenden 'goog.Promise' und schieben sie dann in' goog.Promise.all' – ClojureMostly
Interessanter Vorschlag, da das Google-Framework sowieso importiert wird ... Ich habe es noch nicht versucht, aber im Moment habe ich mich an die Idee gehalten, @alan-thompson gab mir einen Beobachter, der eine Post- Ladehaken, wenn alles fertig ist. Es funktioniert ganz gut für meine Bedürfnisse. – waechtertroll
Es ist auch eine schlechte Idee, da Sie sich mit veränderlichen Zustand beschäftigen und sich darauf verlassen, dass Ihre Logik fehlerfrei ist. Genau dafür wurde "goog.Promise.all" entwickelt. Selbst JavaScript-Programmierer würden diesen Code verstehen. Es ist ein sehr häufiges Muster in der Frontend-Entwicklung! – ClojureMostly