0

レシピを表示する Clojurescript アプリを作成しようとしています。

関連するコードは次のとおりです ( gistとしても入手可能):

(defn load-recipes [data]
  (go (if (not (:loaded? @data))
        (let [recipes-data (<! (fetch-recipes data))]
          (om/update! data :recipes recipes-data)
          (om/update! data :loaded? true))
        (println "Data already loaded"))))

(defn define-routes [data]
  (defroute home-path "/" []
    (om/update! data :view :home))
  (defroute "/random" []
    (go (loop [loaded? (:loaded? (om/value data))]
          (if-not loaded? (do (println "Waiting for data...")
                              (recur (:loaded? (om/value data))))
                  (do (om/update! data :tag
                                  (rand-nth
                                   (vec (apply set/union (map :tags (:recipes @data))))))
                      (om/update! data :view :random)))))))

(defn app-view [data owner]
  (reify
    om/IWillMount
    (will-mount [_]
      (do
        (load-recipes data)
        (define-routes data)))
    om/IDidMount
    (did-mount [_]
      #_(fetch-recipes data))
    om/IRender
    (render [_]
      (html data))))

私が達成したいこと:

  • まず、非同期 http 呼び出しを使用してレシピを取得します。チャネルを返す cljs-http.client を使用しています
  • secretary ライブラリを使用してルートを定義します。/random ルートでは、ランダムなレシピを選択したいと考えています。これは、データがフェッチされ、アプリケーション アトムで更新された場合にのみ発生します。

私が今得ているのは、ブラウザの無限ループです。何が起こっていますか?

別のオプションは、最初にデータを取得する必要があるすべてのルートを go ブロックでラップ(<! (load-recipes))し、最初の行に配置することです。

PS:結局

(defn ensure-recipes-loaded [data]
  (go (if (not (:loaded? (om/value data)))
        (do (om/update! data :view :loading)
            (let [recipes-data (<! (fetch-recipes data))]
              (om/update! data :recipes recipes-data)
              (om/update! data :loaded? true)))
        (println "Data already loaded"))))

(defn define-routes [data]
  (defroute home-path "/" []
    (om/update! data :view :home))
  (defroute "/random" []
    (go
      (<! (ensure-recipes-loaded data))
      (do (om/update! data :tag
                      (rand-nth
                       (vec (apply set/union (map :tags (:recipes @data))))))
          (om/update! data :view :random))))
  (defroute "/random/:tagname" [tagname]
    (go (<! (ensure-recipes-loaded data))
        (om/update! data :tag tagname)
        (om/update! data :view :random)))

  (defroute "/recipe/:link" [link]
    (go (<! (ensure-recipes-loaded data))
        (om/update! data :view :recipe)
        (om/update! data :permalink link)))

  (defroute "*" [*]
    (go (<! (ensure-recipes-loaded data))
        (om/update! data :view :default))))
4

1 に答える 1

2

内部に (パーキング) チャネル操作を何も持たないコンストラクトを使用しloopて待機することは、core.async の精神に完全に反します。JavaScript はシングル スレッドであるため、実行スレッドを保留しないと、他の処理を実行する機会がないことに注意してください。

ロード操作が完了したときに閉じるチャネルを用意します。ブロックする必要がある場合は、そのチャネルから読み取るようにしてください。が返さnilれた場合は完了であり、ブロックされた場合は、目的の待機操作があります。待機中に定期的に何かをしたい場合は、そのチャネルとタイムアウトの両方から読み取ります。

于 2014-06-30T15:37:53.027 に答える