我想在ClojureScript中創建一個文件預加載器。我的想法是這樣的模式:ClojureScript文件預加載器 - 函數或模式來模擬promise?
(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
所以我的主要功能可以繼續下去,直到它需要的資源,然後等待他們,這在Clojure的效果很好。
不幸的是,諾言在ClojureScript中不存在,所以我該如何解決這個問題?有promesa爲基於core.async頻道的CLJS帶來了承諾,但它只允許等待單一功能執行的類似未來的承諾,這不足以滿足我的需求(至少在我昨天一直在想的方面...)。
任何建議來解決這個問題?也許使用完全不同的模式?我想讓代碼儘可能簡單,以說服我的團隊成員試用CLJ/S。
編輯:
艾倫的第二個想法後:
(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))
同時,我曾試圖用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)))
不知道哪個版本更好。
使用'goog.Promise',然後將它們推到'goog。Promise.all' – ClojureMostly
有趣的建議,因爲谷歌框架被導入反正...我還沒有嘗試過,但此刻我堅持@ alan-thompson的想法給了我,並使用了一個觀察者,當一切完成時加載掛鉤。它適合我的需求。 – waechtertroll
這也是一個壞主意,因爲你處理可變狀態,並依靠你的邏輯無缺陷。這正是「goog.Promise.all」所做的。即使JavaScript編碼器會理解該代碼。這是前端開發中非常普遍的模式! – ClojureMostly